第十届蓝桥杯大赛青少年省赛C++组试题真题(2019年)

文章讲述了如何通过编程控制水下探测器在指定深度范围内移动,同时介绍了四个编程问题,涉及投票评选、商品优惠计算和迷宫路径计数,要求编写算法模拟决策过程并输出结果。
摘要由CSDN通过智能技术生成

网易云课

水下探测器

题目描述

水下探测器可以潜入湖中在任意水深进行科学探索。湖水的最大深度为 h 米,即它在湖底时到水面的距离,0≤h≤100;探测器最初的水下深度为 s 米,0≤s≤h;当探测器不在水面(当前深度大于 0)时,每个 u 指令可使它上浮 1 米,而当探测器在水面时,u 指令是无效的;当探测器不在湖底(当前深度小于 h)时,每个 d 指令可使它下沉 1 米,而当探测器在湖底时,d 指令是无效的;在执行到无效指令时,探测器不做任何操作而继续执行下一指令。

输入格式

第一行:h 和 s,以空格分开。0≤s≤h≤100,

第二行:长度不超过 100 的指令字符串,串中仅包含字母 u 或 d。

输出格式

代表探测器在执行指令后的水下深度的数字。

样例

9 1
uduudd
2

提示

水深9米,探测器在水下1米处,

字符u代表向上1米,探测器上浮到0米处,

字符d代表向下1米,探测器下沉到1米处,

字符u代表向上1米,探测器上浮到0米处,

字符u代表向上1米,探测器已经在水面,不能上浮,依然在0米处,

字符d代表向下1米,探测器下沉到1米处,

字符d代表向下1米,探测器下沉到2米处,

最终结果为2。

参考程序

#include <bits/stdc++.h>
using namespace std;

int main() {

	int h, s;
	string op;

	cin >> h >> s >> op;

	for(auto x : op){
		if(x == 'u' && s > 0) s--;
		else if(x == 'd' && s < h) s++;
	}

	cout << s;

	return 0;
}

小猫吃鱼

题目描述

明明家从1号站点出发,开车去旅游,一共要经过n个站点,依次为2 , 3 , … , n。

由于明明带上了心爱的小猫,在每个站点都要为小猫提供一条鱼用做美餐(包括1号站点)。

除了1号站点只能吃1号站点买的鱼,其它站点既可以吃当地买的鱼,也可以吃之前经过的站点买了存入车载冰箱中的鱼。

但车载冰箱消耗的电能来自汽油,所以每条鱼用冰箱保存到下一站的费用与各站点的汽油价格有关。

为使问题简化,我们约定:

  1. 车从某站开出时油箱中都是此站点刚加的汽油。
  2. 车载冰箱能容纳一路上需要的所有鱼。

即:每条鱼的费用既包括购买时的费用,也包括用冰箱保存鱼的费用。

为了降低小猫吃鱼的总代价,明明预先上网查到了这n个站点的鱼价和汽油价格。并据此算出每个站点买一条鱼的费用以及从该站点到下一站用冰箱保存一条鱼的费用。你能帮明明算出这一路上小猫吃鱼的最小费用吗?

输入格式

第一行:站点数n(2 ≤ n ≤ 100) 。

接下来的n行:每行两个以空格分隔的正整数,表示:这一站买一条鱼的费用,以及从这一站把每条鱼保存到下一站的费用,两个费用均为小于等于10000的正整数。

输出格式

输出最小总费用,是一个正整数。

样例

5
6 3
7 1
3 2
8 3
9 5
29

参考程序

#include <iostream>
#include <cstdio>
#define ff first
#define ww second
using namespace std;

const int N = 1010;

typedef pair<int, int> PII;

int n;

PII q[N];

int main() {
	
	cin >> n;
	for(int i = 1; i <= n; i++)
		cin >> q[i].ff >> q[i].ww;

	int ans = q[1].ff, minv = q[1].ff + q[1].ww;

	for(int i = 2; i <= n; i++){
		minv = min(minv, q[i].ff);
		ans += minv;
		minv = min(minv + q[i].ww, q[i].ff + q[i].ww);
	}

	cout << ans << endl;
	
	return 0;
}

评选最佳品牌

题目描述

n个评委投票,在m个商品中评选一个最佳品牌。

评选采用多轮淘汰制,即:每轮投票,淘汰掉得票最少的候选品牌(得票并列最少的品牌一起淘汰)。

如此一轮轮淘汰下去,如果最后只剩下一个品牌当选,即告评选成功。

但如果在某轮投票中,当时未被淘汰的所有候选品牌(大于等于两个品牌)都并列得票最少,即告评选失败。

如果评选成功就输出当选品牌号。否则输出最后一轮评选时唯一选票数的相反数。

在评选流程中,每个评委的态度都可以用一个序列来表示:例如当m = 5时,某评委的评选态度序列为:3,5,1,2,4。则表示该评委:优先投3号,当3号被淘汰时投5号,当3和5都被淘汰时投1,当3,5,1都被淘汰时投2,仅剩4号时才投4号品牌的票。

选票的序列中可以表示弃权,用0来表示,例如当m = 5时,某评委的评选态度序列为:3,5,0。则表示该评委:优先投3号,当3号被淘汰时投5号,其它情况下不投任何品牌的票。

请你编一个程序,模拟各轮投票的过程,得到评选结果。

输入格式

第一行:m(0 < m < 10) 和n(1 < n < 1000) ,分别表示参加评选的品牌数和参加投票的评委数,之间以空格分隔。

接下来的n行:每行都是长度不超过m的数字字符串,每个字符串表示一个评委的评选态度。

输出格式

输出评选结果。

样例

3 4
123
213
132
10
1
3 4
321
213
231
312
-2

参考程序

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int M = 15, N = 1010, INF = 0x3f3f3f3f;

int m, n;
int a[N][M];	// 所有投票情况 a[i][j] 表示 第 i 个评委,第 j 轮投票的商品
int cnt[M];		// cnt[i] 第 i 个商品投票数累计
bool book[M];	// book[i] = true 第 i 个商品已经被淘汰

bool is_success = true;
int last_piaoshu;
int last_pinpai;

// 统计未被删除商品的投票最大值和最小值
void calc_max_min(int& maxv, int& minv){
	for(int i = 1; i < M; i++)
		if(!book[i]){
			minv = min(minv, cnt[i]);
			maxv = max(maxv, cnt[i]);
		}
}

void work(){

	while(true){
		memset(cnt, 0, sizeof cnt);
		for(int i = 1; i <= n; i++){
			for(int j = 1; j < M; j++){
				int t = a[i][j];
				if(!t) break;
				if(book[t]) continue;
				cnt[t]++;
				break;
			}
		}

		int maxv = -INF, minv = INF;
		calc_max_min(maxv, minv);

		if(maxv > minv){
			for(int i = 1; i < M; i++){
				// 淘汰最小得票的品牌
				if(cnt[i] == minv && !book[i])
					book[i] = true;	
			}
			continue;
		}
		else{
			int sum = 0;
			for(int i = 1; i < M; i++)
				if(cnt[i] == minv){
					sum++;
					last_pinpai = i;
				}

			if(sum == 1) return;
			else{
				last_piaoshu = minv;
				is_success = false;
				return;
			}
		}
	}
	
}

int main() {
	
	cin >> m >> n;	// m种商品,n个评委
	for(int i = 1; i <= n; i++){
		char str[M];
		cin >> str + 1;
		for(int j = 1; str[j]; j++)
			a[i][j] = str[j] - '0';
	}

	work();

	if(is_success) cout << last_pinpai << endl;
	else cout << -last_piaoshu << endl;

	return 0;
}

最大购物优惠

题目描述

小惠听说超市正在打折促销,要制定一个得到最大优惠的购物计划。

小惠的体力可以提起w单位重量的东西,还有一个能装v个单位体积的购物袋,并详细了解了各打折商品的重量、体积及此商品实际优惠的金额。她想在自己体力的限度和购物袋容积限度内,尽可能多地得到购物优惠。

超市规定这些打折商品每种只能购买一件。

请你编写程序,制定一个购买商品的计划,求出小惠能得到的最大优惠金额和实际应购买的各商品序号。

输入格式

第一行:依次为w、v和n(n为商品种类数),所有数值均为不超过100的正整数。

接下来的n行:每行有三个整数,依次为某种商品的重量、体积和让利金额,数值间以空格分开,所有数值均为不超过100的正整数。

输出格式

第一行:小惠能够得到的最大让利金额。

第二行:依次为从小到大排列的商品序号,序号从1开始,序号间用空格分开。若第二行输出的序列不唯一,则输出其最小字典序。

样例

10 9 4
8 3 6
5 4 5
3 7 7
4 5 4
9
2 4

参考程序

#include <iostream>
#include <cstdio>
using namespace std;

const int N = 110;

int W, V, n;
int w[N], v[N], p[N];

int f[N][N][N];  // f[i][j][k] 前i种商品可选,重量限制为j,容积限制k,可以得到的最大优惠

int main() {
  
  	cin >> W >> V >> n;
  	for(int i = 1; i <= n; i++) cin >> w[i] >> v[i] >> p[i];
  
  	for(int i = n; i >= 1; i--){
    	for(int j = 1; j <= W; j++)
          	for(int k = 1; k <= V; k++)
              	if(j >= w[i] && k >= v[i])
                  	f[i][j][k] = max(f[i + 1][j][k], p[i] + f[i + 1][j - w[i]][k - v[i]]);
      			else
                  	f[i][j][k] = f[i + 1][j][k];
    }

  
  	cout << f[1][W][V] << endl;
  
  	int j = W, k = V;
  	for(int i = 1; i <= n; i++){
    	if(j >= w[i] && k >= v[i] && f[i][j][k] == p[i] + f[i + 1][j - w[i]][k - v[i]]){
        	cout << i << " ";
          	j -= w[i];
          	k -= v[i];
        }
    }
	return 0;
}

迷宫

题目描述

把一个n行m列的字符阵列看做一个迷宫,迷宫仅包含 “L” , “Q” , “B” , “S” 中的大写字母(蓝桥杯赛的汉语拼音首字母)。

初始时,你可以从任意一个 “L” 字母开始,移向相邻的 “Q” 字母,然后从此 “Q” 字母出发,移向相邻的 “B” 字母,然后从此 “B” 字母出发,移向相邻的 “S” 字母······。这样,你就算是走过了一个 “LQBS” 字符序列。

接下来,仍然可以从此 “S” 字母出发,移向相邻的 “L” 字母······。重复上述的动作,你就可以不断地走过 “LQBS” 序列。
请注意,所谓相邻仅包含上、下、左、右4个方向,且只能从 L → Q ,从 Q→B ,从 B→S ,从 S→L 。

可以想象,由于选择的出发点不同,我们有可能在迷宫中走过无数次的 “LQBS” ,或者是有限次的 “LQBS” ,或者一次也走不了。

请你编写程序,求出在给定的迷宫中,我们最多可以走过多少次 “LQBS” ?

输入格式

第一行:正整数n,m(0 < n , m < 100) ,表示迷宫的规模为n行m列。

接下来的n行:每行m个符合题意的字母,字母间无空格。

输出格式

输出一个整数。即:如果在迷宫中可以无限次地走过 “LQBS” ,则输出 -1 ,否则,输出可以走过 “LQBS” 的最多次数。

样例

1 2
LQ
0
4 4
BLQB
BBQS
SBQL
QQQQ
2

参考程序

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int N = 110;

int n, m;
char g[N][N];

bool bookS[N][N], book[N][N];

int cnt, ans = 0;

bool flag = false;

int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};

void dfs(int x, int y){
	if(g[x][y] == 'S' && !bookS[x][y]) cnt++;
  
  	bookS[x][y] = true;
  
  	for(int i = 0; i < 4; i++){
    	int nx = x + dx[i], ny = y + dy[i];
      	if(nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
      	if((g[x][y] == 'L' && g[nx][ny] == 'Q') ||
           (g[x][y] == 'Q' && g[nx][ny] == 'B') ||
           (g[x][y] == 'B' && g[nx][ny] == 'S') ||
           (g[x][y] == 'S' && g[nx][ny] == 'L')){
        		if(book[nx][ny]){
            		flag = true;
                  	return;
                }
          		book[nx][ny] = true;
          		dfs(nx, ny);
          		book[nx][ny] = false;
        }	
    }
}

int main() {
  
  	cin >> n >> m;
  
  	for(int i = 0; i < n; i++) cin >> g[i];
  	
  	for(int i = 0;  i < n; i++){
    	for(int j = 0; j < m; j++){
        	if(g[i][j] == 'L'){
            	memset(book, 0, sizeof book);
              	cnt = 0;
              	book[i][j] = true;
              	dfs(i, j);
              	if(flag){
                	puts("-1");
                  	return 0;
                }
              	ans += cnt;
            }
        }
    }
  
  	cout << ans << endl;

	return 0;
}
  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值