目录
组队
年号字串
数列求值
数的分解
迷宫
特别数的和
完全二叉树的权值
等差数列
后缀表达式
灵能传输
组队
作为篮球队教练,你需要从以下名单中选出 1 号位至 5 号位各一名球员,组成球队的首发阵容。
每位球员担任 1 号位至 5 号位时的评分如下表所示。请你计算首发阵容 1号位至 5 号位的评分之和最大可能是多少?
试题 A: 组队 2第十届蓝桥杯大赛软件类省赛 C/C++ 大学 B 组
编号 1 号位 2 号位 3 号位 4 号位 5 号位
97 90 0 0 0
92 85 96 0 0
0 0 0 0 93
0 0 0 80 86
89 83 97 0 0
82 86 0 0 0
0 0 0 87 90
0 97 96 0 0
0 0 89 0 0
95 99 0 0 0
0 0 96 97 0
0 0 0 93 98
94 91 0 0 0
0 83 87 0 0
0 0 98 97 98
0 0 0 93 86
98 83 99 98 81
93 87 92 96 98
0 0 0 89 92
0 99 96 95 81
(如果你把以上文字复制到文本文件中,请务必检查复制的内容是否与文档中的一致。在试题目录下有一个文件 team.txt,内容与上面表格中的相同,请注意第一列是编号)
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
思路:直接暴力搜索就可以了,不过这道题也能直接看出来.
#include <iostream>
using namespace std;
int visited[21];
int pp[21][6];
int mmax = 0;
void dfs(int p, int sum)
{
if(p > 5)
{
if(sum > mmax)
{
mmax = sum;
}
}
else
{
for(int i=1; i<=20; i++)
{
if(visited[i] == 0)
{
visited[i] = 1;
dfs(p+1, sum+pp[i][p]);
visited[i] = 0;
}
}
}
}
int main()
{
for(int i=1; i<=20; i++)
{
visited[i] = 0;
for(int j=1; j<=5; j++)
{
cin>>pp[i][j];
}
}
dfs(1, 0);
cout<<mmax<<endl;
return 0;
}
答案:490
年号字串
小明用字母A 对应数字1,B 对应2,以此类推,用Z 对应26。对于27 以上的数字,小明用两位或更长位的字符串来对应,例如AA 对应27,AB 对 应28,AZ 对应52,LQ 对应329。 请问2019 对应的字符串是什么?
手算:
如AA:
27%26=1 ->对应A
27//26=1
1%26=1 ->对应A 所以27(10进制)转换为26进制为AA(329)LQ同理:
329%26=17 ->对应Q
329//26=12
12%26=12 ->对应L,所以329(10进制)转换为26进制为LQ题目要求的2019同理:
2019%26=17 ->对应Q
2019//26=77
77%26=25 ->对应Y
77//26=2
2%26=2 ->对应B,所以2019(10进制)转26进制为BYQ,有功夫写代码,感觉手算都快些
代码:
#include <iostream>
using namespace std;
void solve(int n) {
if (!n) {
return ;
}
solve(n / 26);
cout << (char)(n % 26 + 64);
}
int main() {
solve(2019);
return 0;
}
答案:BYQ
数列求值
代码:
#include<iostream>
using namespace std;
int f[20190324];
int main(){
f[0] = f[1] = f[2] = 1;
for(int i = 3; i < 20190324; i++){
f[i] = (f[i - 1] + f[i - 2] + f[i - 3]) % 10000;
}
cout<<f[20190323]<<endl;
return 0;
}
答案:4659
数的分解
思路:这是一道填空题,你只要计算出结果即可。用暴力的方法做,不用考虑时间,要注意一个数分成三个数,根据排列组合知有六种排序方式,所以结果要除以6.
#include<bits/stdc++.h>
using namespace std;
int check(int n){
while(n){
int t = n % 10;
n = n / 10;
if(t == 2 || t == 4)
return 0;
}
return 1;
}
int main(){
int ans = 0;
for(int i = 1; i <2019; i++){
if(check(i))
for(int j = i + 1; j <2019; j++){
if(check(j)){
int k = 2019 - i - j;
if(k > j && check(k))
ans++;
}
}
}
cout<<ans<<endl;
return 0;
}
答案:40785
迷宫
下图给出了一个迷宫的平面图,其中标记为1 的为障碍,标记为0 的为可 以通行的地方。 010000 000100 001001 110000 迷宫的入口为左上角,出口为右下角,在迷宫中,只能从一个位置走到这 个它的上、下、左、右四个方向之一。 对于上面的迷宫,从入口开始,可以按DRRURRDDDR 的顺序通过迷宫, 一共10 步。其中D、U、L、R 分别表示向下、向上、向左、向右走。 对于下面这个更复杂的迷宫(30 行50 列),请找出一种通过迷宫的方式, 其使用的步数最少,在步数最少的前提下,请找出字典序最小的一个作为答案。 请注意在字典序中D<L<R<U。
01010101001011001001010110010110100100001000101010
00001000100000101010010000100000001001100110100101
01111011010010001000001101001011100011000000010000
01000000001010100011010000101000001010101011001011
00011111000000101000010010100010100000101100000000
11001000110101000010101100011010011010101011110111
00011011010101001001001010000001000101001110000000
10100000101000100110101010111110011000010000111010
00111000001010100001100010000001000101001100001001
11000110100001110010001001010101010101010001101000
00010000100100000101001010101110100010101010000101
11100100101001001000010000010101010100100100010100
00000010000000101011001111010001100000101010100011
10101010011100001000011000010110011110110100001000
10101010100001101010100101000010100000111011101001
10000000101100010000101100101101001011100000000100
10101001000000010100100001000100000100011110101001
00101001010101101001010100011010101101110000110101
11001010000100001100000010100101000001000111000010
00001000110000110101101000000100101001001000011101
10100101000101000000001110110010110101101010100001
00101000010000110101010000100010001001000100010101
10100001000110010001000010101001010101011111010010
00000100101000000110010100101001000001000000000010
11010000001001110111001001000011101001011011101000
00000110100010001000100000001000011101000000110011
10101000101000100010001111100010101001010000001000
10000010100101001010110000000100101010001011101000
00111100001000010000000110111000000001000000001011
10000001100111010111010001000110111010101101111000
代码文章来源地址https://www.toymoban.com/news/detail-409371.html
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<queue>
#include<set>
using namespace std;
#define N 30
#define M 50
char map[N][M];
int dir[4][2]={{1,0},{0,-1},{0,1},{-1,0}};//D<L<R<U
char ch[4]={'D','L','R','U'};
int vis[N][M]={0};
struct point
{
int x,y;
string road;
point(int a,int b)
{
x=a;
y=b;
}
};
void bfs()
{
queue<point> q;
point p(0,0);
p.road="";
q.push(p);
vis[0][0]=1;
while(!q.empty())
{
point t=q.front();
q.pop();
if(t.x==N-1&&t.y==M-1)
{
cout<<t.road<<endl;
break;
}
for(int i=0;i<4;i++)
{
int dx=t.x+dir[i][0];
int dy=t.y+dir[i][1];
if(dx>=0&&dx<N&&dy>=0&&dy<M)
{
if(map[dx][dy]=='0'&&!vis[dx][dy])
{
point tt(dx,dy);
tt.road=t.road+ch[i];//记录路径
q.push(tt);
vis[dx][dy]=1;
}
}
}
}
}
int main()
{
for(int i=0;i<N;i++)
{
for(int j=0;j<M;j++)
scanf("%c",&map[i][j]);
getchar();//读掉回车
}
bfs();
return 0;
}
答案:DDDDRRURRRRRRDRRRRDDDLDDRDDDDDDDDDDDDRDDRRRURRUURRDDDDRDRRRRRRDRRURRDDDRRRRUURUUUUUUULULLUUUURRRRUULLLUUUULLUUULUURRURRURURRRDDRRRRRDDRRDDLLLDDRRDDRDDLDDDLLDDLLLDLDDDLDDRRRRRRRRRDDDDDDRR
特别数的和
代码
#include<bits/stdc++.h>
using namespace std;
int check(int n){
while(n){
int t = n % 10;
n = n / 10;
if(t == 2 || t == 0 || t == 1 || t == 9)
return 1;
}
return 0;
}
int main(){
int n;
int sum = 0;
cin>>n;
for(int i = 1; i <= n; i++){
if(check(i)){
sum += i;
}
}
cout<<sum<<endl;
return 0;
}
完全二叉树的权值
思路:边输入边处理,我们容易知道,每一行的最后一个数的下标都是等于(2^n)-1,比如第二行的最后一个数等于2^2-1=3,第三行的最后一个数等于2^3-1=7,用deep表示当前深度,从当前这行的第一项加到最后一项然后和最大值max_sum比较。
代码:
#include<bits/stdc++.h>
using namespace std;
int Ai[100005];
int main(){
int N;
int deep = 1; //深度
int sum = 0; //每行的和
long long max_sum = -100000000000; //最大的和
int max_deep = 1;
cin>>N;
for(int i = 1; i <= N; ++i){
cin>>Ai[i];
sum += Ai[i];
if(i == pow(2, deep) - 1){
if(max_sum < sum){ //注意不要取等号,因为题目要最小的深度
max_deep = deep;
max_sum = sum;
}
sum = 0;
++deep;
}
}
cout<<max_deep<<endl;
return 0;
}
等差数列
思路
等差数列的任意两项之差为公差的倍数。(a n − a 1 = ( n − 1 ) d , n ≥ 2 a_n-a_1=(n-1)d, n\ge2a
n −a 1 =(n−1)d,n≥2)拿样例来说,2, 6, 4, 10, 20,排序之后为2, 4, 6, 10, 20,与首项的差为2, 4, 8, 18。要使得等差数列最短就要使公差尽可能的大,就是要求差的最大公约数。n个数的最大公约数为求前两个的gcd,再用求出gcd与后面的数依次求。证明?不会 等差数列需要注意公差为0的情况 用到的知识1.等差数列的通项公式,注意公差为0的情况。2.欧几里得算法又称辗转相除法。
代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
int a[N];
int ans;
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i++) scanf("%d", &a[i]);
sort(a, a + n);
for (int i = 1; i < n; i++)
ans = gcd(ans, a[i] - a[0]);
if (ans == 0) cout << n << endl;
else cout << (a[n - 1] - a[0]) / ans + 1<< endl;
return 0;
}
后缀表达式
思路: 分4种情况,
- 减号=0,没办法只能全部加起来
- 负数数目=0,排除了第1种情况,有减号,所以一定是其他数的和-最小的数
- 全为负数,这种最容易忽略,排除上述2种情况,所以只要有减号,一定是其他所有数的绝对值-最大负数的绝对值
- 其他情况,都是所有数的绝对值的和
代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
ll a[200005], sum = 0, mi = 1000000009;
int n, m, fu = 0;
bool cmp(int a, int b) { return a > b; }
int main()
{
scanf("%d%d", &n, &m);
for (int i = 0; i < n + m + 1; i++)
{
scanf("%lld", &a[i]);
if (a[i] < 0) fu++;
sum += a[i];
mi = min(mi, a[i]);
}
if (m == 0) printf("%lld\n", sum);
else
{
if(fu == 0) printf("%lld\n", sum - mi - mi);
else
{
if (fu == n + m + 1) //***全是负数
{
sum = 0; mi = 1000000009;
for (int i = 0; i < n + m + 1; ++i)
{
sum += abs(a[i]);
mi = min(mi, abs(a[i]));
}
printf("%lld\n", sum - mi - mi);
}
else
{
sum = 0;
for (int i = 0; i < n + m + 1; ++i) sum += abs(a[i]);
printf("%lld\n", sum);
}
}
}
return 0;
}
灵能传输
思路:这题题量有点大。。。简单来说就是给定一组数,我们的目标是通过两种操作使得其中的绝对值最大的数达到最小,这两种操作是:
1、如果 a[i] > 0 并且 a[i - 1] 或者 a[i+1] 小于 0,我们可以将 a[i] 借给 i-1 元素和 i+1 元素,同时 a[i] 要变成 -a[i]。
2、如果 a[i] < 0 并且 a[i - 1] 或者 a[i+1] 大于 0,我们可以将 a[i-1] 和 a[i+1] 各借 abs(a[i]) 给 i 元素,之后 i 元素的值变成 -a[i] 也就是正数(a[i] 本身是小于 0 的),同时 a[i - 1] 和 a[i + 1] 要减掉 abs(a[i])。
我们考虑几种情况:
1、所有的数字都为正数或者都为负数,即所有的数字都同号。这种情况是没法借的,因为不符合操作要求,因此这种情况求出数组中绝对值最大的数即可。
2、对于 a[i],如果 a[i] 是正数,并且 a[i - 1] 和 a[i + 1] 至少有一个负数,那么我们的目标就是把那个绝对值最大的负数的绝对值缩小,这个时候如果另一边是正数,则需要考虑操作之后是否会产生新的绝对值更大的正数,比如现在有三个数:5 5 -6,如果我们把中间那个 5 按上面的操作 1 变换之后:10 -5 -1,绝对值最大数变成了 10,而之前是 6,显然不行。如果这三个数是这样的:1 5 -7,那么我们就可以按操作 1 变换:6 -5 -2,最大绝对值从 7 减小到了 6,是可行的。那么变换条件是什么呢?这里假设 a[i - 1] 是正数,a[i + 1] 是负数,那么条件可以写成:a[i - 1] + a[i] < abs(a[i + 1])。而如果 a[i - 1] 和 a[i + 1] 都是负数的时候,当两边的绝对值有一个大于 a[i] 时,就可以进行操作 1 变换。
3、对于 a[i] 是负数的时候,如果 a[i - 1] 是负数, a[i+1] 是正数,那么确保 a[i + 1] > abs(a[i] + a[i-1]),就可以进行操作 2 变换,如果两边都是正数则只要有一边的值大于 abs(a[i]) 时就可以进行操作 2 变换 文章来源:https://www.toymoban.com/news/detail-409371.html
代码
#include <cstdio>
#include <cmath>
#include <iostream>
using namespace std;
const int MAXN = 300010;
int nums[MAXN];
// 判断 a 和 b 是否异号
bool judgeYi(int a, int b) {
return a > 0 && b < 0 || a < 0 && b > 0;
}
int main() {
int T, n;
cin >> T;
while (T--) {
cin >> n;
// 标志负数和正数是否出现
bool hasNe = false, hasPo = false;
int res = 0;
for (int i = 0; i < n; i++) {
scanf("%d", &nums[i]);
if (nums[i] < 0) {
hasNe = true;
} else if (nums[i] > 0) {
hasPo = true;
}
}
// 如果数组中同时存在正负数,则判断能否进行操作 1 和 操作 2
if (hasNe && hasPo) {
bool canNext;
do {
canNext = false;
for (int i = 1; i < n - 1; i++) {
// nums[i] 和 nums[i-1] 或 nums[i+1] 异号
if (judgeYi(nums[i], nums[i-1]) || judgeYi(nums[i], nums[i+1])) {
if (nums[i] > 0) {
// nums[i-1] 和 nums[i+1] 异号,
// 这里的 if 和 else 可以合并,为了逻辑清晰,这里分开写
if (judgeYi(nums[i-1], nums[i+1])) {
if ((nums[i-1] > 0 && abs(nums[i+1]) > nums[i-1] + nums[i]) ||
(nums[i+1] > 0 && abs(nums[i-1]) > nums[i+1] + nums[i])) {
nums[i+1] += nums[i];
nums[i-1] += nums[i];
nums[i] = -nums[i];
canNext = true;
}
} else { // nums[i-1] 和 nums[i+1] 同号,都 < 0
if (abs(nums[i-1]) > nums[i] || abs(nums[i+1]) > nums[i]) {
nums[i+1] += nums[i];
nums[i-1] += nums[i];
nums[i] = -nums[i];
canNext = true;
}
}
} else if (nums[i] < 0) {
// nums[i-1] 和 nums[i+1] 异号
if (judgeYi(nums[i-1], nums[i+1])) {
if ((nums[i-1] > 0 && nums[i-1] > abs(nums[i+1] + nums[i])) ||
(nums[i+1] > 0 && nums[i+1] > abs(nums[i-1] + nums[i]))) {
nums[i+1] += nums[i];
nums[i-1] += nums[i];
nums[i] = -nums[i];
canNext = true;
}
} else { // nums[i-1] 和 nums[i+1] 同号,都 > 0
if (nums[i-1] > abs(nums[i]) || nums[i+1] > abs(nums[i])) {
nums[i+1] += nums[i];
nums[i-1] += nums[i];
nums[i] = -nums[i];
canNext = true;
}
}
}
}
}
} while (canNext);
}
int t;
// 求绝对值最大的值
for (int i = 0; i < n; i++) {
res = max(res, abs(nums[i]));
}
cout << res << endl;
}
return 0;
}
到了这里,关于蓝桥杯——2019第十届C/C++真题[省赛][B组]的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!