2023年5月电子学会青少年C/C++软件编程(五级)等级考试试卷及答案解析

1、问题求解

给定一个正整数N,求最小的M满足比N大且M与N的二进制表示中有相同数目的1。
举个例子,假如给定N为78,二进制表示为1001110,包含4个1,那么最小的比N大的并且二进制表示中只包含4个1的数是83,其二进制是1010011,因此83就是答案。
时间限制:1000
内存限制:65536
输入
输入若干行,每行一个数N(1 ≤ N ≤ 1000000),如果这行为0表示输入结束。
输出
对于每个N,输出对应的M。

样例输入
1
2
3
4
78
0
样例输出
2
4
5
8
83

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define INF 999999999
#define N 1001
using namespace std;
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF&&n)
    {
        int cnt=0;
        int temp=n;
        while(temp>0)
        {
            if(temp%2)
                cnt++;
            temp/=2;
        }
        int sum=0;
        while(1)
        {
            temp=++n;
            while(temp>0)
            {
                if(temp%2)
                    sum++;
                temp/=2;
            }
            if(cnt==sum)
            {
                cout<<n<<endl;
                break;
            }
            sum=0;
        }
    }
    return 0;
}

2、算24

给出4个小于10个正整数,你可以使用加减乘除4种运算以及括号把这4个数连接起来得到一个表达式。现在的问题是,是否存在一种方式使得得到的表达式的结果等于24。 这里加减乘除以及括号的运算结果和运算的优先级跟我们平常的定义一致(这里的除法定义是实数除法)。 比如,对于5,5,5,1,我们知道5 * (5 – 1 / 5) = 24,因此可以得到24。又比如,对于1,1,4,2,我们怎么都不能得到24。
时间限制:6000
内存限制:65536
输入
输入数据包括多行,每行给出一组测试数据,包括4个小于10个正整数。最后一组测试数据中包括4个0,表示输入的结束,这组数据不用处理。
输出
对于每一组测试数据,输出一行,如果可以得到24,输出“YES”;否则,输出“NO”。

样例输入
5 5 5 1
1 1 4 2
0 0 0 0
样例输出
YES
NO

//青少年考级竞赛题库(tiku.scratchor.com)搜集整理,感谢网友提供代码!
#include <iostream>
#include<cmath>
#include<bits/stdc++.h>
#define EPS  1e-6
using namespace std;
bool iszero(double c){
    if(fabs(c) <= EPS) return 1;
    else return 0;
}
bool suan24(double* a,int k){
    if(k==1 && iszero(a[0]-24)) return 1;
    double b[5];
    for(int i=0;i<k-1;i++)
        for(int j=i+1;j<k;j++) {
            int z = 0;
            for (int xx = 0; xx < k; xx++)
                if (xx != i && xx != j) b[z++] = a[xx];
            b[z] = a[i] + a[j];
            if (suan24(b, k - 1)) return 1;
            b[z] = a[i] - a[j];
            if (suan24(b, k - 1)) return 1;
            b[z] = a[j] - a[i];
            if (suan24(b, k - 1)) return 1;
            b[z] = a[i] * a[j];
            if (suan24(b, k - 1)) return 1;
            if (a[j] != 0) {
                b[z] = a[i] / a[j];
                if (suan24(b, k - 1)) return 1;
            }
            if (!iszero(a[i])) {
                b[z] = a[j] / a[i];
                if (suan24(b, k - 1)) return 1;
            }
    }
    return 0;
}
int main()
{
    while(1)
    {
        double a[6];
        int sum=0;
        for(int i=0;i<4;++i)
        {
            cin>>a[i];
            sum+=a[i];
        }
        if(sum==0)break;
        bool flag=suan24(a,4);
        if(flag==1)cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
//        cout<<flag<<endl;
    }
    return 0;
}

3、忍者道具

忍者道具有很多种,苦无,飞镖,震爆弹。L君热衷于收集忍者道具,现在他有N个道具,每个道具的重量分别是C1、C2…CN。现在他想把这N个道具装到载重量为W的工具包里,请问他最少需要多少个工具包?
时间限制:1000
内存限制:65536
输入
第一行包含两个用空格隔开的整数,N和W。 接下来N行每行一个整数,其中第i+1行的整数表示第i个道具的重量Ci。
输出
输出一个整数,最少需要多少个工具包。

样例输入
5 1996
1
2
1994
12
29
样例输出
2

提示
对于100%的数据,1<=N<=18,1<=Ci<=W<=10^8。

//青少年考级竞赛题库(tiku.scratchor.com)搜集整理,感谢网友提供代码!
#include <iostream>
using namespace std;
const int MAXN = 18;
int used[MAXN];
int W;
int m, n, ans = (1 << 30);
int item[MAXN];
int bag[MAXN];
void dfs(int x, int sum) {
    if (sum >= ans) return;
    if (x == n) {
        ans = min(ans, sum);
        return;
    }
    for (int i = 0; i < sum; ++i) {
        if (bag[i] >= item[x]) {
            bag[i] -= item[x];
            dfs(x + 1, sum);
            bag[i] += item[x];
        }
    }
    bag[sum] -= item[x];
    dfs(x + 1, sum + 1);
    bag[sum] += item[x];
}
int main() {
    cin >> n >> m;
    for (int i = 0; i < n; ++i) {
        cin >> item[i];
        bag[i] = m;
    }
    dfs (0, 1);
    cout << ans << endl;
    return 0;
}


4、泳池

小C在一个排水系统不太好的学校上学。又是一个下雨天,学校里高低不平积了很多水。小C突发奇想:如果大雨一直下,多久以后我可以在学校里游泳呢?

学校是 N x N 的坐标方格 grid 中,每一个方格的值 grid(i,j)表示在位置 (i,j) 的高度。现在开始下雨了。当时间为 t 时,此时雨水导致方格中任意位置的水位为 t 。你可以从一个方格游向四周相邻的任意一个方格,但是前提是此时水位必须同时淹没这两个方格。假定小C的游动是不耗时的。

现在小C从坐标方格的左上(0,0)出发。最少耗时多久他才能到达坐标方格的右下平台 (N-1, N-1)?
时间限制:1000
内存限制:65536
输入
第一行有一个整数N,以下是一个N*N的方阵,代表各处的高度。 输入范围: 2 ≤ N ≤ 300 0 ≤ Height ≤ 10000000
输出
输出一个整数,代表最少等待时间T

样例输入
样例输入1:
2
0 2
1 3

样例输入2:
5
0 1 2 3 4
24 23 22 21 5
12 13 14 15 16
11 17 18 19 20
10 9 8 7 6

样例输出
样例输出1:
3

样例输出2:
16

提示
样例1:时间为3时,才可以游向平台(1,1),此时水位为3。 样例2:时间为16时,水位为16,此时才能保证(0,0)和(4,4)是联通的(请自行找出一条通路)。

//青少年考级竞赛题库(tiku.scratchor.com)搜集整理,感谢网友提供代码!
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int maze[305][305];
bool reach[305][305];
int dx[4] = { -1,1,0,0 };
int dy[4] = { 0,0,-1,1 };
int N;
struct point {
    int x, y;
    point(int a,int b):x(a),y(b){}
};
bool canreach(int t) {
    if (maze[0][0] > t)
        return false;
    memset(reach, 0, sizeof(reach));
    reach[0][0] = 1;
    queue<point>myqueues;
    myqueues.push(point(0, 0));
    while (!myqueues.empty()) {
        point top = myqueues.front();
        myqueues.pop();
        if (top.x == N - 1 && top.y == N - 1)
            return true;
        for (int i = 0; i < 4; i++) {
            int tx = top.x + dx[i];
            int ty = top.y + dy[i];
            if (tx < 0 || tx >= N || ty < 0 || ty >= N)
                continue;
            if (reach[tx][ty])
                continue;
            if (maze[tx][ty] > t)
                continue;
            reach[tx][ty] = 1;
            myqueues.push(point(tx, ty));
        }
    }
    return false;
}
int main() {
    memset(maze, 0, sizeof(maze));
    cin >> N;
    int L = 10000000, R = 0;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            cin >> maze[i][j];
            L = min(maze[i][j], L);
            R = max(maze[i][j], R);
        }
    }
    int result= 10000000;
    while (L <= R) {
        int mid = (L + R) / 2;
        if (canreach(mid)) {
            R = mid - 1;
            result = min(result, mid);
        }
        else
            L = mid + 1;
    }
    cout << result << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青少年等级考试周老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值