2019年第十届蓝桥杯C/C++ 省赛B组真题+题解

 答案和代码仅供参考,比赛时倒数第二题花了太多时间,导致没时间写填空题最后一题和大题最后一题,唉,总的来说今年的题目比去年的简单,今年的蓝桥杯可真是“暴力杯”。先放这么多东西吧,以后再更新,欢迎大佬们提供代码,哈哈哈哈哈哈

试题链接:https://pan.baidu.com/s/1ZJ09aV-denor-MSGOnJpDA 
提取码:bqnz 
复制这段内容后打开百度网盘手机App,操作更方便哦

目录

试题A:组队

试题B:年号字串

试题C:数列求值

试题D:数的分解 

试题E:迷宫 

试题F:特别数的和 

试题G:完全二叉树的权值 

试题H:等差数列 

试题I:后缀表达式 

试题J:灵能传输


 试题A:组队

试题A:很简单的题目,不多说,直接搜,代码:答案490

#include<bits/stdc++.h>
using namespace std;
int team[20][6];
int vis[20];
int max_sum = 0;
void dfs(int index, int sum){
	if(index == 6){
		max_sum = max(max_sum, sum);
		return;
	}
	for(int i = 0; i < 20; i++){
		if(!vis[i]){
			vis[i] = 1;
			dfs(index + 1, sum + team[i][index]);
			vis[i] = 0;
		}
	}
}
int main(){
	freopen("team.txt", "r", stdin); //读team.txt文件 ,输入重定向 
        //注意把team.txt放到同一级目录下,或者把这行注释掉,手动输入 
	for(int i = 0; i < 20; i++)
		for(int j = 0; j < 6; j++)
			cin>>team[i][j];
	dfs(1, 0);
	cout<<max_sum<<endl;
	return 0;
}

 数据:

1 97 90 0 0 0
2 92 85 96 0 0
3 0 0 0 0 93
4 0 0 0 80 86
5 89 83 97 0 0
6 82 86 0 0 0
7 0 0 0 87 90
8 0 97 96 0 0
9 0 0 89 0 0
10 95 99 0 0 0
11 0 0 96 97 0
12 0 0 0 93 98
13 94 91  0 0 0
14 0 83 87 0 0
15 0 0 98 97 98
16 0 0 0 93 86
17 98 83 99 98 81
18 93 87 92 96 98
19 0 0 0 89 92
20 0 99 96 95 81

试题B:年号字串

试题B:刚开始以为是26进制,,,,,,其实不是,代码:答案BYQ

#include<bits/stdc++.h>
using namespace std;
int main(){
	string str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	char ans[5];
	int index = 0;
	int n = 2019;
	while(n){
		int t = n % 26;
		n = n / 26;
		ans[index] = str[t - 1];
		index++; 
	}
	for(int i = index - 1; i >= 0; i--){
		cout<<ans[i];
	}
	return 0;
}

试题C:数列求值

试题C:题目要求求最后四位数字,那我们只要每次求完f(n)再模上10000就行了,因为加法的后4位只和加数后4位有关,代码:答案4659

#include<bits/stdc++.h>
using namespace std;
int f[20190324];//数组空间太大,要放到main外面
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;
}

试题D:数的分解 

试题D:很简单,两层for循环i和j,j从i+1开始保证ijk是升序的,k=2019-i-j,判断ijk包不包含2和4就行了,代码:答案40785

#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;
}

试题E:迷宫 

数据:

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

试题E:这个题目和蓝桥练习系统算法提高部分的学霸的迷宫http://lx.lanqiao.cn/problem.page?gpid=T291这个题目基本一样,所以好好刷练习系统是没毛病的。看官网原题:

答案(可能不对,仅供参考):UUUULLDLLLLLLLULLLUUURUULUUUUUUUUUUUULULULLDDDLLLLUUUULULLLLLDLLLULLUUULLLLDDLDDDDDDDDRRRDDDDLLLLDDRRRDDDDRRDDDRDDLLDLLDLDLLLULULLLLULULUURRRUULLUULUURUUURRUURRRURUUURUULLLLLLLLLUUUUUULL

思路:先广搜,方向按照DLRU来搜,这样搜到的第一个答案就是字典序最小的,用一个队列,首先0(x),0(y)入队,然后按照DLRU这个方向依次判断是否可以走。用一个vis[i][j]存放当前节点深度,起点为1,下面为vis[i][j]运行结果,其实到这一步答案都可以自己看下图走出来,不过为了便捷,还是用深搜把答案搞出来。

代码: 

#include<bits/stdc++.h>
using namespace std;
string maze[30]; //存放迷宫 
int vis[30][50]; //是否访问过 
char ans[1000]; //答案序列 
queue<int> que; 
int next_x[4] = {1, 0, 0, -1}; //注意x,y的顺序,D<L<R<U搜出来的必定字典序最小
int next_y[4] = {0, -1, 1, 0}; //{x, y} = {1, 0}表示向下 ,{0, -1}左,{0, 1}右,{-1, 0}上 
int DLRU[4] = {'D', 'L', 'R', 'U'};
int flag = 0; //用于dfs中 
void bfs(int x, int y){
	que.push(x);
	que.push(y);
	vis[x][y] = 1;
	while(!que.empty()){
		int current_x = que.front();
		que.pop();
		int current_y = que.front();
		que.pop();
		if(current_x == 29 && current_y == 49) //如果走到了终点就退出循环 
			break;
		for(int i = 0; i < 4; i++){ //这里是判断四个方向是否可到达 
			int next_step_x = current_x + next_x[i];
			int next_step_y = current_y + next_y[i];
			if(next_step_x < 30 && next_step_x >= 0 && next_step_y < 50 && next_step_y >= 0){ //不能越界 
				if(maze[next_step_x][next_step_y] == '0') //如果是0代表可达 
					if(vis[next_step_x][next_step_y] == 0){ //判断这个点有没有访问过,等于0代表没有访问过 
						que.push(next_step_x);
						que.push(next_step_y);
						vis[next_step_x][next_step_y] = vis[current_x][current_y] + 1; //当前节点vis值等于上一层+1,这样方便后面寻找走的路径 
					}
			}
		}
	}
}
void dfs(int index, int x, int y){//这里深搜是从终点开始,所以要按照字典序最小,那么方向顺序就和正向相反,就是URLD 
	if(flag == 1) return; //如果找到了第一个答案序列,不进行下面的搜索 
	if(index == 1){
		flag = 1; // 用来判断是否搜到第一个答案,如果搜到了接下来的搜索就不用干了 
		for(int i = 2; i <= vis[29][49]; i++)
			cout<<ans[i];
		cout<<endl;
		return;
	}
	for(int i = 3; i >= 0; i--){ //顺序要相反 
		int pre_x = x + next_x[i];
		int pre_y = y + next_y[i];
		if(pre_x < 30 && pre_x >= 0 && pre_y < 50 && pre_y >= 0){
			if(vis[pre_x][pre_y] + 1 == vis[x][y]){
				ans[index] = DLRU[i]; 
				dfs(index - 1, pre_x, pre_y);
				ans[index] = ' ';
			}
		}
	}
}
int main(){
	freopen("maze.txt", "r", stdin); //注意把maze.txt放到同一级目录下,或者把这行注释掉,手动输入 
	for(int i = 0; i < 30; i++)
		cin>>maze[i];
	bfs(0, 0);
	dfs(vis[29][49], 29, 49);
	for(int i = 0; i < 30; i++){
		for(int j = 0; j < 50; j++){
//			cout<<vis[i][j]<<" ";
			printf("%3d ", vis[i][j]);
		}
		cout<<endl;
	}
	return 0;
}

试题F:特别数的和 

 

试题F(注意题目输入格式描述错误,是一个整数):这个题目我觉得就是填空题D的变形,看测试用例才1到10000,直接搜,代码:

#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;
}

试题G:完全二叉树的权值 

试题G:思路:边输入边处理,我们容易知道,每一行的最后一个数的下标都是等于(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;
}

试题H:等差数列 

 

试题H:我拿到这个题目首先就是想到先排序,再求最小的公差,然后((最大值-最小值)/最小的公差)+1,然而这个是错的思路,唉,又丢分了。。。。。比如 输入6 2 4 7 10 12 20,如果用这个公式算那么得到答案为10,但实际为19,所以是求排序完后求每两个相邻数的最大公因数。代码:

#include<bits/stdc++.h>
using namespace std;
int Ai[100005];
int main(){
	int N;
	cin>>N;
	for(int i = 0; i < N; i++)
		cin>>Ai[i];
	sort(Ai, Ai + N);
	int min_d = Ai[1] - Ai[0]; //升序排的序,所以公差大于0 
	if(min_d == 0) //如果 Ai[1] - Ai[0]等于0,说明这些数必定全部相等,那最小值就是N 
		cout<<N<<endl;
	else{
		int gcd = min_d; 
		for(int i = 2; i < N; i++){
			min_d = __gcd(min_d, Ai[i] - Ai[i - 1]); 
		}
		cout<<(Ai[N - 1] - Ai[0]) / min_d + 1<<endl;
	}
	return 0;
}

试题I:后缀表达式 

 

试题I:这个该死的题目,考试废了我好多时间。。。

试题J:灵能传输

 

试题J:考试没看题目,你懂的。。。