2019年第十届蓝桥杯国赛C++A组

蓝桥杯历年国赛真题汇总:Here

最后编辑时间:

2021年5月27日

统一声明
如果不写默认带有常用头文件
如果不表明主函数默认表示在 void solve(){}
默认使用

using namespace std;
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using ll = long long;

填空题答案速览

  1. 180414

试题 A: 三升序列

【问题描述】

对于一个字母矩阵,我们称矩阵中的一个三升序列是指在矩阵中找到三个 字母,它们在同一行,同一列,或者在同一 45 度的斜线上,这三个字母从左向 右看、或者从上向下看是递增的。

​ 例如,如下矩阵中

YQPD
BKEZ
AFYV

​ 有BKZ、BEZ、AFY、AFV、AKP、DEF 等 6 个三升序列。注意当三个字母 是从左下到右上排列时,从左向右看和从上向下看是不同的顺序。

​ 对于下面的 30 行 50 列的矩阵,请问总共有多少个三升序列?(如果你把 以下文字复制到文本文件中,请务必检查复制的内容是否与文档中的一致。在 试题目录下有一个文件 inc.txt,内容与下面的文本相同)

VLPWJVVNNZSWFGHSFRBCOIJTPYNEURPIGKQGPSXUGNELGRVZAG
SDLLOVGRTWEYZKKXNKIRWGZWXWRHKXFASATDWZAPZRNHTNNGQF
ZGUGXVQDQAEAHOQEADMWWXFBXECKAVIGPTKTTQFWSWPKRPSMGA
BDGMGYHAOPPRRHKYZCMFZEDELCALTBSWNTAODXYVHQNDASUFRL
YVYWQZUTEPFSFXLTZBMBQETXGXFUEBHGMJKBPNIHMYOELYZIKH
ZYZHSLTCGNANNXTUJGBYKUOJMGOGRDPKEUGVHNZJZHDUNRERBU
XFPTZKTPVQPJEMBHNTUBSMIYEGXNWQSBZMHMDRZZMJPZQTCWLR
ZNXOKBITTPSHEXWHZXFLWEMPZTBVNKNYSHCIQRIKQHFRAYWOPG
MHJKFYYBQSDPOVJICWWGGCOZSBGLSOXOFDAADZYEOBKDDTMQPA
VIDPIGELBYMEVQLASLQRUKMXSEWGHRSFVXOMHSJWWXHIBCGVIF
GWRFRFLHAMYWYZOIQODBIHHRIIMWJWJGYPFAHZZWJKRGOISUJC
EKQKKPNEYCBWOQHTYFHHQZRLFNDOVXTWASSQWXKBIVTKTUIASK
PEKNJFIVBKOZUEPPHIWLUBFUDWPIDRJKAZVJKPBRHCRMGNMFWW
CGZAXHXPDELTACGUWBXWNNZNDQYYCIQRJCULIEBQBLLMJEUSZP
RWHHQMBIJWTQPUFNAESPZHAQARNIDUCRYQAZMNVRVZUJOZUDGS
PFGAYBDEECHUXFUZIKAXYDFWJNSAOPJYWUIEJSCORRBVQHCHMR
JNVIPVEMQSHCCAXMWEFSYIGFPIXNIDXOTXTNBCHSHUZGKXFECL
YZBAIIOTWLREPZISBGJLQDALKZUKEQMKLDIPXJEPENEIPWFDLP
HBQKWJFLSEXVILKYPNSWUZLDCRTAYUUPEITQJEITZRQMMAQNLN
DQDJGOWMBFKAIGWEAJOISPFPLULIWVVALLIIHBGEZLGRHRCKGF
LXYPCVPNUKSWCCGXEYTEBAWRLWDWNHHNNNWQNIIBUCGUJYMRYW
CZDKISKUSBPFHVGSAVJBDMNPSDKFRXVVPLVAQUGVUJEXSZFGFQ
IYIJGISUANRAXTGQLAVFMQTICKQAHLEBGHAVOVVPEXIMLFWIYI
ZIIFSOPCMAWCBPKWZBUQPQLGSNIBFADUUJJHPAIUVVNWNWKDZB
HGTEEIISFGIUEUOWXVTPJDVACYQYFQUCXOXOSSMXLZDQESHXKP
FEBZHJAGIFGXSMRDKGONGELOALLSYDVILRWAPXXBPOOSWZNEAS
VJGMAOFLGYIFLJTEKDNIWHJAABCASFMAKIENSYIZZSLRSUIPCJ
BMQGMPDRCPGWKTPLOTAINXZAAJWCPUJHPOUYWNWHZAKCDMZDSR
RRARTVHZYYCEDXJQNQAINQVDJCZCZLCQWQQIKUYMYMOVMNCBVY
ABTCRRUXVGYLZILFLOFYVWFFBZNFWDZOADRDCLIRFKBFBHMAXX

答案:180414

#include<bits/stdc++.h>
using namespace std;
char text[30][500];
void copytext() {
    char c[500];
    int line = 0;
    FILE *fp = fopen("inc.txt", "r");
    if (fp == NULL) {
        cout << "failed to open file!" << endl;
    } else {
        while (fgets(c, 500, fp))
            strcpy(text[line++], c);
    }
    fclose(fp);
}
int main() {
    int temp1, temp2;
    int hang = 30; int lie = 50;
    cin >> hang >> lie;
    int i, j, k, r = 0, count = 0;
    copytext();
    //求每行的三升序列
    for (i = 0; i < hang; i++)
        for (j = 0; j < lie; j++)
            for (k = j + 1; k < lie; k++)
                if (text[i][j] < text[i][k] && text[i][k] < 90)
                    for (r = k + 1; r < lie; r++)
                        if (text[i][k] < text[i][r])
                            count++;
    //求每列的三升序列
    for (i = 0; i < lie; i++)
        for (j = 0; j < hang; j++)
            for (k = j + 1; k < hang; k++)
                if (text[j][i] < text[k][i] && text[k][i] < 90)
                    for (r = k + 1; r < hang; r++)
                        if (text[k][i] < text[r][i])
                            count++;
    //求左下到右上对角线的三升序列
    for (i = 2; i < hang; i++)
        for (j = 0; j < lie; j++) {
            k = j; r = i;
            while (r - 1 >= 0 && k + 1 < lie) {
                if (text[i][j] < text[r - 1][k + 1] && text[r - 1][k + 1] < 90) {
                    temp1 = r - 2; temp2 = k + 2;
                    while (temp1 >= 0 && temp2 < lie) {
                        if (text[r - 1][k + 1] < text[temp1][temp2])
                            count++;
                        temp1--; temp2++;
                    }
                }
                k++; r--;
            }
        }
    //求右上到左下对角线的三升序列
    for (i = 0; i < hang; i++)
        for (j = 2; j < lie; j++) {
            k = j; r = i;
            while (k - 1 >= 0 && r + 1 < hang) {
                if (text[i][j] < text[r + 1][k - 1] && text[r + 1][k - 1] < 90) {
                    temp1 = r + 2; temp2 = k - 2;
                    while (temp2 >= 0 && temp1 < hang) {
                        if (text[r + 1][k - 1] < text[temp1][temp2])
                            count++;
                        temp2--; temp1++;
                    }
                }
                k--; r++;
            }
        }
    //求左上到右下对角线的三升序列
    for (i = 0; i < hang; i++)
        for (j = 0; j < lie; j++) {
            k = j; r = i;
            while (r + 1 < hang && k + 1 < lie) {
                if (text[i][j] < text[r + 1][k + 1] && text[r + 1][k + 1] < 90) {
                    temp1 = r + 2; temp2 = k + 2;
                    while (temp1 < hang && temp2 < lie) {
                        if (text[r + 1][k + 1] < text[temp1][temp2])
                            count++;
                        temp1++; temp2++;
                    }
                }
                k++; r++;
            }
        }
    cout << count << endl;
    return 0;
}

试题 B: 最优旅行

【问题描述】

​ 中国的高铁四通八达,乘坐方便,小明经常乘坐高铁在城市间旅游。

​ 现在,小明又有了一个长假,他打算继续乘坐高铁旅游。这次,他打算到 下面的城市旅游。

​ 上海、广州、长沙、西安、杭州、济南、成都、南京、昆明、郑州、天津、 太原、武汉、重庆、南昌、长春、沈阳、贵阳、福州。

​ 小明打算从北京出发,游览以上每个城市正好一次,最终回到北京。在每 个城市(除北京外),小明都至少停留 24 小时。而当小明决定从一个城市去往 另一个城市时,他只会选择有直接高铁连接的城市,不会在中途换乘转车。

​ 在试题目录下有一个文件 trip.txt 保存了小明可以选择的车次,小明不会 选择其他车次。 小明出发的时间是第 1 天的中午 12:00。

​ 请问,小明游览完以上城市正好一 次,最终回到北京,最快需要多少分钟(请注意单位为分钟)

答案:

// trip.txt
车次  出发站 到达站 出发时间 到达时间
G169   北京   上海   16:40   22:35
G21    北京   上海   19:08   23:40
G18    上海   北京   17:55   22:36
G68    广州   北京   11:13   21:10
G67    北京   广州   12:13   22:19
G1305  上海   广州   15:25   23:38
G86    广州   上海   08:00   14:50
G6122  广州   长沙   21:00   23:36
G6117  长沙   广州   17:55   20:39
G502   长沙   北京   07:36   14:24
G503   北京   长沙   14:41   21:14
G1359  上海   长沙   15:37   20:59
G1348  长沙   上海   09:00   13:41
G362   西安   上海   08:49   14:45
G1936  上海   西安   16:12   22:54
G87    北京   西安   14:00   18:20
G88    西安   北京   13:30   17:55
G98    西安   广州   09:57   17:39
G836   广州   西安   11:24   20:09
G1404  广州   杭州   15:56   23:25
G20    杭州   北京   07:48   12:20
G39    北京   杭州   19:04   23:22
G7355  上海   杭州   21:30   22:28
G7558  杭州   上海   07:06   08:12
G300   济南   上海   06:50   11:40
G333   北京   济南   19:55   21:55
G336   济南   北京   07:45   09:33
G2056  广州   济南   08:05   18:34
G2058  济南   广州   10:14   20:49
G350   成都   北京   07:00   14:46
G89    北京   成都   06:53   14:38
G1888  成都   南京   11:28   22:00
G7180  上海   南京   10:05   11:29
G7003  南京   上海   08:00   09:39
G7613  南京   杭州   16:19   17:40
G7604  杭州   南京   12:09   13:30
G1540  昆明   南京   10:20   21:14
G1539  南京   昆明   09:05   19:40
G2883  成都   昆明   08:51   14:29
G2884  昆明   成都   12:16   17:57
G1538  昆明   郑州   08:46   18:48
G1537  郑州   昆明   10:38   20:49
G2001  郑州   西安   07:52   10:24
G2002  西安   郑州   08:10   10:29
G2231  西安   重庆   17:06   22:56
G2232  重庆   西安   07:05   12:37
G8594  重庆   成都   06:50   08:07
G8599  成都   重庆   22:12   23:29
G1709  天津   重庆   08:05   19:39
G1710  重庆   天津   10:49   22:45
G8901  北京   天津   22:10   22:45
G8928  天津   北京   19:08   19:46
G2609  天津   太原   10:40   14:15
G2610  太原   天津   14:43   18:12
G1954  太原   上海   12:26   21:17
G1952  上海   太原   08:10   17:28
G686   郑州   太原   13:17   17:16
G688   太原   郑州   17:38   21:38
G1864  太原   杭州   12:50   21:10
G1862  杭州   太原   07:14   15:50
G91    北京   太原   08:40   11:07
G92    太原   北京   08:33   11:00
G694   太原   武汉   16:37   22:29
G692   武汉   太原   09:48   16:00
G1722  武汉   上海   08:00   11:53
G1720  上海   武汉   13:51   17:50
G858   西安   武汉   15:18   19:48
G856   武汉   西安   09:17   14:27
G365   天津   武汉   14:56   20:41
G366   武汉   天津   14:30   20:32
G294   长沙   天津   08:47   16:56
G292   天津   长沙   10:58   18:50
G696   长沙   太原   09:23   17:55
G698   太原   长沙   10:46   18:18
G1391  杭州   昆明   11:43   22:53
G1392  昆明   杭州   09:06   20:18
G1514  昆明   南昌   16:00   22:54
G1511  南昌   昆明   08:25   15:38
G1462  南昌   杭州   12:24   15:28
G1451  杭州   南昌   12:30   15:26
G1244  济南   长春   07:42   15:07
G1242  长春   济南   15:33   22:35
G8033  沈阳   长春   06:42   08:40
G1290  长沙   长春   07:21   21:09
G1292  长春   长沙   08:47   22:08
G400   长春   北京   08:32   14:48
G399   北京   长春   15:20   21:45
G1886  南京   成都   08:07   17:54
G579   南京   长沙   09:27   14:10
G580   长沙   南京   15:53   20:40
G1484  贵阳   南京   07:58   18:02
G2335  南京   贵阳   12:07   21:58
G2105  长沙   贵阳   13:17   16:55
G2116  贵阳   长沙   08:11   11:26
G2201  郑州   成都   07:10   13:19
G2212  成都   郑州   16:57   23:04
G1814  上海   郑州   14:15   18:12
G370   郑州   上海   07:33   12:02
G1274  武汉   沈阳   07:23   19:03
G1272  沈阳   武汉   07:32   19:20
G2869  重庆   昆明   07:43   11:55
G2870  昆明   重庆   14:52   19:09
G1335  重庆   上海   08:48   20:56
G1333  上海   重庆   11:39   23:29
G1759  南昌   重庆   07:08   14:45
G1761  重庆   南昌   15:12   22:23
G1493  南京   南昌   13:00   17:21
G1496  南昌   南京   09:04   13:25
G5314  南昌   福州   08:13   11:09
G5312  福州   南昌   18:30   21:25
G1256  长春   上海   11:53   22:54
G1258  上海   长春   09:08   20:05
G1284  沈阳   成都   07:02   21:47
G1282  成都   沈阳   09:06   23:13
G217   北京   沈阳   13:30   17:15
G218   沈阳   北京   08:11   11:58
G2604  沈阳   太原   15:34   23:00
G2602  太原   沈阳   07:44   15:14
G8664  贵阳   成都   19:15   22:35
G8691  成都   贵阳   11:11   14:31
G2958  贵阳   广州   14:03   20:26
G2960  广州   贵阳   07:27   13:43
G1521  武汉   贵阳   08:01   13:25
G1524  贵阳   武汉   14:23   19:33
G1609  福州   广州   08:16   14:15
G1607  广州   福州   14:55   21:05
G1696  昆明   福州   11:11   22:02
G1698  福州   昆明   08:41   19:28
G1636  福州   上海   12:26   16:55
G1631  上海   福州   07:54   12:15
G1642  福州   杭州   14:45   18:32
G1641  杭州   福州   18:55   22:38

答案:

试题 C: 骰子制造

No.C

答案:

试题 D: 序列求和

答案:

试题 E: 无方集合

答案:

试题 F: 大胖子走迷宫

题目描述
小明是个大胖子,或者说是个大大胖子,如果说正常人占用 1 × 1 的面积,小明要占用 5 × 5 的面积。

由于小明太胖了,所以他行动起来很不方便。当玩一些游戏时,小明相比小伙伴就吃亏很多。

小明的朋友们制定了一个计划,帮助小明减肥,

计划的主要内容是带小明玩一些游戏,让小明在游戏中运动消耗脂肪,走迷宫是计划中的重要环节。

迷宫可以看成是一个由 n × n 个方阵组成的方阵,正常人每次占用方阵中 1 × 1 的区域,而小明要占用 5 × 5 的区域。

小明的位置定义为小明最正中的一个方格。迷宫四周都有障碍物。

为了方便小明,朋友们把迷宫的 起点 设置在了第 3 行第 3 列,终点 设置在了第 n − 2 行第 n − 2 列。

小明在时刻 0 出发,每单位时间可以向当前位置的上、下、左、右移动单位 1 的距离,也可以停留在原地不动。

小明走迷宫走得很辛苦,如果他在迷宫里面待的时间很长,由于消耗了很多脂肪,他会在时刻 k 变成一个胖子,只占用 3 × 3 的区域。

如果待的时间更长,他会在时刻 2k 变成一个正常人,只占用 1 × 1 的区域。注意,当小明变瘦时迷宫的起点和终点不变。

请问,小明最少多长时间能走到迷宫的终点。注意,小明走到终点时可能变瘦了也可能没有变瘦。

输入格式
输入的第一行包含两个整数 n, k。
接下来 n 行,每行一个由 n 个字符组成的字符串,字符为 + 表示为空地,字符为 * 表示为阻碍物。

输出格式
输出一个整数,表示答案。

样例输入

9 5
+++++++++
+++++++++
+++++++++
+++++++++
+++++++++
***+*****
+++++++++
+++++++++
+++++++++

样例输出

16

数据范围
对于 30% 的评测用例,1 ≤ n ≤ 50。
对于 60% 的评测用例,1 ≤ n ≤ 100。
对于所有评测用例,1 ≤ n ≤ 300,1 ≤ k ≤ 1000。

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

struct node {
    int x, y, time;
};

const int N = 310;

int n, k;
char g[N][N];
bool vis[N][N];

int dr[3] = {2, 1, 0};                                                              // 表示胖子不同时刻的半径
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};

int bfs() {
    queue<node> q;
    q.push({3, 3, 0});
    vis[3][3] = true;
    while (q.size()) {
        node t = q.front();
        q.pop();
        if (t.x == n - 2 && t.y == n - 2) return t.time;
        if (t.time / k < 2) q.push({t.x, t.y, t.time + 1});                         // 体积为 1 后,就不用原地不动了
        for (int i = 0; i < 4; i ++) {
            int a = t.x + dx[i], b = t.y + dy[i];
            int fat = t.time / k > 2 ? 0 : dr[t.time / k];                          // 此时胖子的半径
            if (a - fat < 1 || a + fat > n || b - fat < 1 || b + fat > n) continue;
            if (vis[a][b]) continue;
            bool flag = false;                                                      // 判断胖子所占范围内是否有障碍物
            for (int j = a - fat; j <= a + fat; j ++)
                for (int k = b - fat; k <= b + fat; k ++)
                    if (g[j][k] == '*') flag = true;
            if (flag) continue;
            q.push({a, b, t.time + 1});
            vis[a][b] = true;
        }
    }
    return -1;
}

int main() {
    cin >> n >> k;
    for (int i = 1; i <= n; i ++ ) cin >> g[i] + 1;
    cout << bfs() << endl;
    return 0;
}

试题 G: 估计人数

【问题描述】
给定一个 N × M 的方格矩阵,矩阵中每个方格标记 0 或者 1 代表这个方格
是不是有人踩过。
已知一个人可能从任意方格开始,之后每一步只能向右或者向下走一格。
走了若干步之后,这个人可以离开矩阵。这个人经过的方格都会被标记为 1,
包括开始和结束的方格。注意开始和结束的方格不需要一定在矩阵边缘。
请你计算至少有多少人在矩阵上走过。
【输入格式】
输入第一行包含两个整数 N、M。
以下 N 行每行包含 M 个整数 (0/1),代表方格矩阵。
【输出格式】
输出一个整数代表答案。
【样例输入】

5 5
00100
11111
00100
11111
00100

【样例输出】

3

【数据规模与约定】
对于所有评测用例,1 ≤ N, M ≤ 20,标记为 1 的方格不超过 200 个。

https://blog.csdn.net/qq_43655831/article/details/115557704

试题 H: 轨道炮

【样例输入】

 4 
 0 0 1 R 
 0 10 1 R 
 10 10 2 D 
 2 3 2 L

【样例输出】

3

【评测用例规模与约定】 对于所有评测用例,

\(1 ≤ N ≤ 1000,−1000000 ≤ X_i , Y_i ≤ 1000000,0 ≤ Vi ≤ 1000000\)

试题 I: 分考场

【问题背景】

古语有云:春风得意马蹄疾,一日看尽长安花。
当然在一场考试中所有人都春风得意马蹄疾是不可能的,尤其是碰到一些毒瘤出题人的时候。

【问题描述】

又到了每月一次的月考,又是 xf 老师出题。

上一次 xf 老师出的题太毒瘤了,平均分只有 40 多,同学们都非常不满意,毕竟别的科的平均分都是 80 多。

这次 xf 为了不被同学们寄刀片,想了一个办法:只公布所有考场的平均分的平均分。这样他就可以通过调整考场的分配方式,使得平均分显得高。(每个考场都可以容纳无限人)

每次考试也不是所有同学都参加的,只有学号在 [l,r] 这个区间中的同学会参加。

他想知道对于每次考试,他调整过考场后,所有考场的平均分的平均分的最大值。

当然,同学们也可能会努力学习或整日颓废使成绩发生改变。

【输入格式】

输入的第一行包含一个整数 n。

第二行包含 n 个整数,第 i 个数 vi,表示开始时每个同学的成绩。

第三行包含一个整数 q,表示有 q 次操作。

之后 q 行,每行描述一个操作,第一个数表示操作类型。

如果操作为 1 p x,表示学号为 p 的同学分数变为 x。

如果操作为 2 l r k, 表示把学号在 [l,r] 中的同学分成 k 个考场,求这 k 个考场的平均分的平均分的最大值。

【输出格式】

对于每个 2 操作输出一行,四舍五入保留正好 3 位小数。

【样例输入】

5
5 3 4 2 1
5
2 1 4 3
1 4 8
2 3 5 3
1 2 2
2 1 3 2

【样例输出】

3.833
4.333
4.000

【样例说明】

第一个操作询问学号在 [1, 4] 之间的同学分成 3 个考场的平均分的平均分的最大值,最优策略是:{1}, {2, 4}, {3},平均分是

第二个操作把学号为 4 的同学的分数变为 8。

第三个操作询问学号在 [3, 5] 之间的同学分成 3 个考场的平均分的平均分的最大值,最优策略是:{3}, {4}, {5}。

第四个操作把学号为 2 的同学分数变为 2。

第五个操作询问学号在 [1, 3] 之间的同学分成 2 个考场的平均分的平均分的最大值,最优策略是:{1}, {2 3}。

【评测用例规模与约定】

对于全部评测用列,n ≤ 200000, q ≤ 200000, 任意时刻同学的分数 vi ≤ 10^9,k ≤ r − l + 1。

评测时将使用 10 个评测用例测试你的程序,每个评测用例的限制如下:

试题 J: 逃出生天

待补

posted @ 2021-05-27 20:56  Koshkaaa  阅读(772)  评论(0编辑  收藏  举报