十四届蓝桥青少C++组2023年3月评测--中高级

23年3月12日C++中高级

第1子卷: 03-12-C++-中高级-选择题

1.单选题 | 执行cout << '9'*3;语句后,输出的结果是(   )。
*选择题严禁使用程序验证,选择题不答或答错都不扣分

A   27

B    9*3

C   999

D   171

正确答案: D  

2.单选题 | 下列选项中,判断a不等于0且b不等于0的正确的条件表达式是(   )。
*选择题严禁使用程序验证,选择题不答或答错都不扣分

A   !(a==0&&b==0) 

B    !a=0&&!b=0

C   a && b

D   !((a!=0)&&(b!=0))

正确答案: C  

3.单选题 | 执行语句int a[3][4] = {{1, 2}, {3}, {4, 5, 6, 7}};后,a[1][2]和a[2][1]的值分别为:(   )。
*选择题严禁使用程序验证,选择题不答或答错都不扣分

A   2、3

B    0、5

C   2、5

D   5、0

正确答案: B  

4.单选题 | 已定义:int a = 02023, b = 0X212; a + b的值是(   )。
*选择题严禁使用程序验证,选择题不答或答错都不扣分

A    八进制数4771

B    十进制数1573

C   十进制数2553

D   十六进制数9f9

正确答案: B  

5.单选题 | 执行以下代码,输出的结果是(   )。
#include<iostream>
using namespace std;
int func(int x)
{
    if (x <= 4)
        return 2 * x - 1;
    else if (x > 7)
        return func(x - 4) + x;
    else
        return func(x + 3) + 2;
}
 
int main()
{
    cout << func(10);
    return 0;
}
*选择题严禁使用程序验证,选择题不答或答错都不扣分

A   26

B    29

C   38

D   45

正确答案: C  

第2子卷: 03-12-C++-中高级-编程题

1.编程题  |15分

时间限制:C/C++语言 1000MS;其他语言 3000 MS
内存限制:C/C++语言 65536KB;其他语言 589824KB
问题描述:
编程实现:促销活动
题目描述:
某超市搞促销活动,活动内容:购物金额每满200元(含200元)就可以享受“满200减25”的优惠。
已知小维的购物金额为N(1<N<1000000),请计算出享受优惠后他需要支付多少元。
  
例如:N=430,购物金额为430元时,满足2次“满200减25”的条件,所以可以减去2个25元,最后结账
时需支付的金额为380元(380=430-2×25)。
输入描述:
输入一个正整数N(1<N<1000000),表示购物金额(单位:元)
输出描述:
输出一个正整数,表示享受优惠后需要支付的金额(单位:元)
输入样例:
430
输出样例:
380

支持语言:
C++

标程:

#include<iostream>
using namespace std;
int main()
{
    int n;
    cin >> n;
    cout << n - n / 200 * 25;
    return 0;
}

2.编程题  | 

问题描述:

18分

编程实现:相邻身高差
题目描述:
有N(4≤N≤100)名同学站成一队,已知每名同学的身高 (单位:厘米),请比较该队中任意相邻两名同
学的身高差(取正值),并输出最大的身高差。
 
例如:N = 8,8名同学的身高分别是151、120、144、182、160、158、147、161,
相邻两名同学的身高差依次是31、24、38、22、2、11、14,其中最大身高差是38。
输入描述:
第一行输入一个正整数N(4≤N≤100),表示站队的同学人数
第二行输入N个正整数(80≤正整数≤220),表示队列中学生的身高(单位:厘米),相邻两个正整数之
间用一个空格隔开
输出描述:
输出一个非负整数,表示相邻两名同学中最大身高差
输入样例:
8
151 120 144 182 160 158 147 161
输出样例:
38

支持语言:
C++

标程:

#include<iostream>
#include<cmath> 
using namespace std;
const int N = 10000;
int main()
{
    int n, maxgap = 0, pre, nxt = 0;
    cin >> n >> pre;
    for (int i = 2; i <= n; i++)
    {
        cin >> nxt;
        if (abs(nxt - pre) > maxgap)
            maxgap = abs(nxt - pre);
        pre = nxt;
    
    }
    cout << maxgap;
    return 0;
}


3.编程题  | 

20分


问题描述:
编程实现:九进制回文数
提示信息:
回文数:反向排列与原来一样的数就叫做回文数。
例如,12321是回文数,1231不是回文数。
   
九进制数:指逢9进位的一种进位计数制,以0、1、2、3、4、5、6、7、8共九个数码表示。
例如:十进制数9等于九进制数10,十进制数81等于九进制数100,以此类推。
   
题目描述:
给定两个正整数N和M(1≤N≤M≤5000),请计算出N到M之间(含N和M)总共有多少个数满足以下条
件:
1、转换为九进制之后为回文数;
2、转换为九进制后每个数位上的数字都是奇数。
    
例如:
当N=90,M=120,90到120之间(含90和120)总共有2个数满足条件,为91和109。
91转换为九进制为111,是一个回文数,且每个数位上的数字都是奇数;
109转换为九进制为131,是一个回文数,且每个数位上的数字都是奇数;
故输出2。
输入描述:
输入两个正整数N和M(1≤N≤M≤5000),两个正整数之间用一个空格隔开
输出描述:
输出一个整数,表示N到M之间(含N和M)总共有多少个满足条件的正整数
输入样例:
90 120

输出样例:
2

支持语言:
C++

标程:

#include<iostream>
using namespace std;
int main()
{
    int NS = 9, cnt = 0;
    int n, m; 
    cin >> n >> m;
    for (int i = n; i <= m; i++)
    {
        int x = i;
        int a9 = 0, b9 = 0, pos = 1;
        bool f = true;
        while (x)
        {
            if (x % NS % 2 == 0)
            {
                f = false;
                break;
            }
            a9 = a9 * 10 + x % NS;
            b9 = b9 + x % NS * pos;
            pos *= 10;
            x /= NS;
        }
        if (a9 == b9 && f)
        {
            cnt++;
        }
    }
    cout << cnt;
    return 0;
}


4.编程题  | 


25分


问题描述:
编程实现:收集宝石
题目描述:
聪聪在玩冒险岛游戏,为了召唤法力更强大的神龙,他必须尽可能收集更多的魔法宝石,每颗宝石都有不同
的功效。不过在游戏里,几乎每一颗魔法宝石都会和另外一颗宝石相冲。相冲表示这两颗宝石不能同时拥
有。例如,宝石A和宝石B相冲,那么,你可以选择两颗宝石都不收集,也可以只收集宝石A或者只收集宝石
B,但不能同时拥有宝石A和宝石B。
现在给定了游戏里宝石的数量N(2≤N≤100),宝石从1到N依次编号,并给出M对(2≤M≤2000)相冲
的宝石编号,请帮聪聪计算出最多能够收集到多少颗宝石。
   
例如:N=6,M=8时,6颗宝石的编号分别为1、2、3、4、5、6,其中有8对相冲的宝石,对应编号如
下:
1 2
2 3
2 4
2 5
2 6
3 4
4 5
5 6
这表示宝石1和宝石2相冲,宝石2和宝石3、4、5、6都相冲,宝石3和宝石4相冲,宝石4和宝石5相冲,宝
石5和宝石6相冲。
有三个方案收集到的宝石数量最多:(1 3 5)、(1 3 6)、(1 4 6),这些方案里,最多收集到的宝石数
量都是3,所以程序输出3。
输入描述:
第一行输入两个正整数N和M(2≤N≤100,2≤M≤2000),分别表示游戏里的宝石数量和M对相冲的宝
石,两个正整数之间用一个空格隔开
接下来输入M行,每行两个正整数,分别表示相冲的两颗宝石的编号,两个正整数之间用一个空格隔开
输出描述:
输出一个整数,表示聪聪在游戏里最多能够收集到的宝石数量
输入样例:


6 8
1 2
2 3
2 4
2 5
2 6
3 4
4 5
5 6
输出样例:
3

支持语言:
C++标程:

#include <bits/stdc++.h>
using namespace std;
const int NN = 105;
int n, m, a[NN][NN], ans, b[NN];
bool check(int u) {//判断u号钻石已经选好的钻石是否有冲突
    for(int i = 1; i < u; i++) {//枚举u号之前的钻石
        if(a[u][i] && b[i]) {//冲突且已选
            return false;
        }
    }
    return true;
}
void dfs(int u, int sum) {//第u号钻石,之前一共选了sum个钻石
    if(u == n + 1) {//如果所有钻石都找完了
        ans = max(ans, sum);//取最大值
        return;
    }
    //如果剩下的钻石都选也没有已有的最好情况多,返回
    if(ans > sum + (n - u + 1)) return;
    if(check(u)) {//当前钻石与已选钻石没有冲突
        b[u] = 1;//选之
        dfs(u + 1, sum + 1);//继续下一个钻石
    }
    b[u] = 0;//不选
    dfs(u + 1, sum);//继续下一个钻石
}
int main() {
    cin >> n >> m;
    while(m--) {
        int x, y;
        cin >> x >> y;
        a[x][y] = 1;
        a[y][x] = 1;
    }
    dfs(1, 0);//从第一个钻石开始选,目前已选0个
    cout << ans;
 
    return 0;
}

【方法2】

#include<bits/stdc++.h>
using namespace std;
int n,m;
bool a[100][100];
int ans = 1;
int b[100];
void dfs(int x,int step){
	for(int i=x+1;i<=n;i++){
		bool flag = 0;
		for(int j = 1;j<step;j++){
			if(a[i][b[j]] != 0){
				flag = 1;
				break;
			}
		}		 
		if(flag == 0){
			b[step] = i;
			ans = max(ans,step);
			dfs(i,step+1);
		}
	}
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		a[x][y] = a[y][x] = 1;
	}
	for(int i=1;i<n;i++){
		b[1] = i;
		dfs(i,2);
	}
	cout<<ans;
}
/*
6 8
1 2
2 3
2 4
2 5
2 6
3 4
4 5
5 6
*/


5.编程题  | 

30分


问题描述:
编程实现:简易炸弹超人
题目描述:
有一块矩形游戏场地,场地被分成N×M的网格(4≤N≤100,4≤M≤10),其中一部分小方格是水域,另
一部分小方格是陆地。
为防御敌军攻击,玩家需要在游戏场地安置炸弹:
1.炸弹只能安置在陆地上;
2.每颗炸弹爆炸后,可以波及到炸弹所在的小方格,及相邻的上、下、左、右小方格;
3.任意两颗炸弹爆炸后不能波及到同一个小方格。
请帮助玩家计算出如何安置炸弹,可以使炸弹波及到的范围最大,输出最多可以波及到的小方格数量。
    
例如:
N = 4,M = 4,网格中水域和陆地的情况如图1所示:

图中,蓝色区域代表水域,绿色区域代表陆地;安置炸弹的最优方案之一如图2所示;炸弹波及的范围如图
3所示(黑色区域)。
这块4×4的矩形游戏场地最多可以波及到11个小方格,其他方案都不会优于这个结果。
输入描述:
第一行输入两个正整数N和M(4≤N≤100,4≤M≤10),分别表示网格的行数和列数,两个正整数之间以
一个空格隔开
接下来输入N行,每行M个字符(字符只能是大写字母A或B),A表示水域,B表示陆地,字符之间以一个
空格隔开
输出描述:
输出一个整数,表示最多可以波及到的小方格数量
输入样例:
4 4
B A A A
A B A B
B A B B 
A B A A
输出样例:
11

支持语言:
C++标程:

#include<iostream>
#include<bitset>
using namespace std;
char ab;        //读取地形字符
int n, m, dp[110][65][65]; //dp[i][ j][k]为第i行本行状态为j,上一行状态为k合法时的总的炸毁小方格的数量
int st[65];     //st[]:每一行状态的合法性
int cnt;        //炸弹合法状态的数量
int num[110][65];    // num[i][ j] i行 j状态中炸弹的数量
int map[110];   //地图的水域陆地状态,1表示水域,0表示陆地
int ans = 0;    //答案,最多能炸毁小方格的数量
bool checkRow(int x)//判断横向状态是否合法,是返回0
{
    return (x & (x >> 1)) || (x & (x >> 2));
}
bool checkMap(int i, int x) //判断x号状态是否符合地形条件,是返回0
{
    return map[i] & st[x];
}
int main()
 
int main()
{
    cin >> n >> m; //N行M列
    for(int i = 1; i <= n; i++) //读取地图,转换成二进制存储方式,生成的二进制数是倒序,不影响结果
    {
        for(int j = 1; j <= m; j++)
        {
            cin >> ab; //读取字符
            if(ab == 'A') //如果是水域
                map[i] |= 1 << ( j - 1); //存储地图状态,1表示不能放
        }
    }
    
// 显示地图读取内容-二进制
//    for(int i = 1; i <= n; i++)  
//    {
//        cout << bitset<4>(map[i]) << endl;
//    }    
    for(int i = 0; i < (1 << m); i++)
        if(!checkRow(i)) //左右不冲突
            st[++cnt] = i; //存储一行里的合法状态
    
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= cnt; j++)
        {
            int p = st[ j];
            int col = 1;
            while(p > 0) //统计多少个1,表示一行里炸弹的数量
            {
                if(p & 1)
                {
                    num[i][ j] += 5;
                    if(col == 1)    num[i][ j] -= 1;
                    if(i == 1)      num[i][ j] -= 1;
                    if(col == m)    num[i][ j] -= 1;
                    if(i == n)      num[i][ j] -= 1;
                }
                col++;
                p >>= 1;
            }
        }//计算num[i][ j]
    }
    for(int i = 1; i <= cnt; i++) //初始化第1行的数量,只与地形有关
        if(!checkMap(1, i))
            dp[1][i][0] = num[1][i]; //不存在前2行,可随意摆放
    for(int i = 1; i <= cnt; i++) //初始化第2行的数量,遍历每一种状态
    {
        for(int j = 1; j <= cnt; j++) //循环比较各种状态是否冲突
            if(!checkMap(2, i) && !((st[ j]|st[ j]>>1|st[ j]<<1)&st[i])) //地形合法且两行不冲突, 
                dp[2][i][ j] = max(dp[2][i][ j], dp[1][ j][0] + num[2][i]);
    }
    for(int i = 3; i <= n; i++) //从第3行开始dp
    {
        for(int j = 1; j <= cnt; j++) //i行状态
            if(!checkMap(i, j)) //地形合法
            {
                for(int k = 1; k <= cnt; k++) //i-1行状态
                    if(!((st[k]|st[k]>>1|st[k]<<1)&st[ j]))//注意,j,k两状态不能冲突
                    {
                        for(int l = 1; l <= cnt; l++) //i-2行状态
                            if(!(st[ j]&st[l]))   //注意,j、l状态不能冲突
                            {
                                // dp[i][ j][k] = max(dp[i][ j][k], dp[i - 1][k][l] + num[i][ j]);
                                if (dp[i][ j][k] < dp[i - 1][k][l] + num[i][ j])
                                {
                                    dp[i][ j][k] = dp[i - 1][k][l] + num[i][ j];
                                }
                                ans = max(ans, dp[i][ j][k]); //统计最多的炸毁小方格的数量
                            }
                    }
            }
    }
    cout << ans << endl;
    return 0;
}  
  • 16
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值