2019 第十届蓝桥杯省赛C/C++大学B组 试题+题解

第十届蓝桥杯省赛C/C++大学B组 试题+题解

第十届蓝桥杯大赛软件类省赛
C/C++ 大学 B 组

考生须知

考试开始后,选手首先下载题目,并使用考场现场公布的解压密码解压试 题。
考试时间为 4 小时。考试期间选手可浏览自己已经提交的答案,被浏览的 答案允许拷贝。时间截止后,将无法继续提交或浏览答案。
对同一题目,选手可多次提交答案,以最后一次提交的答案为准。
选手必须通过浏览器方式提交自己的答案。选手在其它位置的作答或其它 方式提交的答案无效。
试题包含“结果填空”和“程序设计”两种题型。
结果填空题:要求选手根据题目描述直接填写结果。求解方式不限。不要 求源代码。把结果填空的答案直接通过网页提交即可,不要书写多余的内容。
程序设计题:要求选手设计的程序对于给定的输入能给出正确的输出结果。 考生的程序只有能运行出正确结果才有机会得分。
注意:在评卷时使用的输入数据与试卷中给出的示例数据可能是不同的。 选手的程序必须是通用的,不能只对试卷中给定的数据有效。
对于编程题目,要求选手给出的解答完全符合 GNU C/C++ 标准,不能使 用诸如绘图、Win32API、中断调用、硬件操作或与操作系统相关的 API。
代码中允许使用 STL 类库。
注意: main 函数结束必须返回 0
注意: 所有依赖的函数必须明确地在源文件中 #include ,不能通过 工程设置而省略常用头文件。
所有源码必须在同一文件中。调试通过后,拷贝提交。 提交时,注意选择所期望的编译器类型。

试题 A: 组队 本题总分:5 分

【问题描述】
作为篮球队教练,你需要从以下名单中选出 1 号位至 5 号位各一名球员, 组成球队的首发阵容。
每位球员担任 1 号位至 5 号位时的评分如下表所示。请你计算首发阵容 1 号位至 5 号位的评分之和最大可能是多少?
在这里插入图片描述
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
文件内容:

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

试题A 题解 490

这题的话,我们可以将这些数据直接复制进Excel,然后各项降序排列,选前5个,然后找出最后不同人的每号位最高。
答案为490

试题 B: 年号字串 本题总分:5 分

【问题描述】
小明用字母 A 对应数字 1,B 对应 2,以此类推,用 Z 对应 26。对于 27 以上的数字,小明用两位或更长位的字符串来对应,例如 AA 对应 27,AB 对 应 28,AZ 对应 52,LQ 对应 329。
请问 2019 对应的字符串是什么?
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个大写英文字符串,在提交答案时只填写这个字符串,注意全部大写,填写多 余的内容将无法得分。

试题B 题解

这题为一个10进制到26进制的一个转化。有很多种方法来解这题,我们这边说两种:

解法一:Excel方法:

很巧的是,Excel的横轴也是26进制的,而且也是使用A-Z来表示的,我们只需要将横排拉到2019即可:
在这里插入图片描述
答案为BYQ

解法二:程序方法:

我们可以使用编写程序将十进制转换为26进制,然后用A-Z来表示26进制,所用的算法与十进制-二进制转换一致,代码如下:

#include <iostream>
using namespace std;
int main(){
    int a = 2019;
    string output = "";
    while(a){
        output = output + char(64+a%26);
        a /= 26;
    }
    for(int i = output.length()-1;i >=0 ;i--)
        cout<<output[i];
    return 0;
}

修改:完善边界问题,例如676转换后应为YZ,702转换后应为702,完善后的代码如下:

#include <iostream>
#include <algorithm>
using namespace std;
int main(){
    int a;
    cin>>a;
    string output = "";
    while(a){
        output = output + char(64+a%26);
        a /= 26;
    }
    for(string::iterator it = output.begin();it != output.end();){
        if(*it <= '@') {
            if(it == output.end()-1)
                break;
            *it = char(int('Z')-(int('@')-int(*it)));
            it++;
            *it = char(int(*it)-1);
        } else
            it++;
    }
    reverse(output.begin(),output.end());
    for(string::iterator it = output.begin();it != output.end();it++){
        if(*it == '@')
            continue;
        cout<<*it;
    }
    return 0;
}

试题 C: 数列求值 本题总分:10 分

【问题描述】
给定数列 1, 1, 1, 3, 5, 9, 17, …,从第 4 项开始,每项都是前 3 项的和。求 第 20190324 项的最后 4 位数字。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个 4 位整数(提示:答案的千位不为 0),在提交答案时只填写这个整数,填写 多余的内容将无法得分。

试题C 题解:

这题是一个fibonacci数列的变形,他的解法和fibonacci数列一样,可以使用dp来进行求解,然后再答案只要最后四项,所以当数值大于10000时,我们进行模10000操作,来防止溢出。
代码如下:

#include <iostream>
using namespace std;
int a,b,c;//用来保存3个数,只要有连续三个数,就可以计算出其余的数
void fibonacci(int a1,int a2,int a3){
    int mid = (a1 + a2 + a3)%10000;
    a = a2;
    b = a3;
    c = mid;
}
int main(){
    a=1;
    b=1;
    c=1;
    for(int i=3;i < 20190324; i++){
        fibonacci(a,b,c);
    }
    cout<<c;
    return 0;
}

答案:4659

试题 D: 数的分解 本题总分:10 分

【问题描述】
把 2019 分解成 3 个各不相同的正整数之和,并且要求每个正整数都不包 含数字 2 和 4,一共有多少种不同的分解方法?
注意交换 3 个整数的顺序被视为同一种方法,例如 1000+1001+18 和 1001+1000+18 被视为同一种。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

试题D 题解:

这题只需要三个数递增的搜索,这样就可以保证三个数乱序不重复,然后判断是否满足条件即可,代码如下:

#include<iostream>
using namespace std;
int number = 2019;
bool is_ok(int n){
    int mid;
    while(n){
        mid = n%10;
        if(mid==2||mid==4)
            return false;
        n /= 10;
    }
    return true;
}
int main(){
    int ans = 0;
    for(int i = 1; i < 673; i++){
        for(int j = i+1; j < 1346; j++) {
            for (int k = j+1; k < 2019; k++) {
                if (i + j + k != 2019)
                    continue;
                if (is_ok(i) && is_ok(j) && is_ok(k)) {
                    ans++;
                }
            }
        }
    }
    cout<<ans;
    return 0;
}

答案为:40785

试题 E: 迷宫 本题总分:15 分

【问题描述】
下图给出了一个迷宫的平面图,其中标记为 1 的为障碍,标记为 0 的为可 以通行的地方。
010000
000100
001001
110000
迷宫的入口为左上角,出口为右下角,在迷宫中,只能从一个位置走到这 个它的上、下、左、右四个方向之一。
对于上面的迷宫,从入口开始,可以按DRRURRDDDR 的顺序通过迷宫, 一共 10 步。其中 D、U、L、R 分别表示向下、向上、向左、向右走。
对于下面这个更复杂的迷宫(30 行 50 列),请找出一种通过迷宫的方式, 其使用的步数最少,在步数最少的前提下,请找出字典序最小的一个作为答案。 请注意在字典序中D<L<R<U。(如果你把以下文字复制到文本文件中,请务 必检查复制的内容是否与文档中的一致。在试题目录下有一个文件 maze.txt, 内容与下面的文本相同)
maze.txt内容为:

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

【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个字符串,包含四种字母 D、U、L、R,在提交答案时只填写这个字符串,填 写多余的内容将无法得分。

试题E 题解:

这题是一个迷宫的最短路径求解(最短路径,按字典序排列),这题的解法很明确,就是一个带路径的bfs(广度优先搜索),在搜索出最短路径之后,根据保存的路径进行回溯出所走的路径。
代码如下:

#include<iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <queue>
#include <map>
using namespace std;
char maze[30][50]={0};//存储迷宫信息
char visit[30][50];//访问数组,同时存放到达这个位置时所走的方向
typedef struct ds{//自定义一个结构体,记录行,列,已经走到当前位置的走的方向
    int row;
    int col;
    char director;
}ds;
queue<ds> bfs_que;//bfs使用的待搜索队列
int next_dir[4][2]={//存放4个方向,用于控制下一步的走向,字典序排列
        //D,L,R,U
        {1,0},
        {0,-1},
        {0,1},
        {-1,0}
};
char dir[4] = {'D','L','R','U'};//存放字典序的四个方向
map<char,int> dir_index;
bool is_ok(int row, int col){//判断是否可以走
    return (row >= 0 && row < 30 && col >= 0 && col < 50 && (visit[row][col] == char(0) ) && (maze[row][col] == '0') ) ? true : false;
}
void bfs(){
    ds start={0,0,'S'};//(0,0)为起点,这里面的director设为‘S’,表示起点
    bfs_que.push(start);//将起点加入待搜索队列
    ds now;//当前的结点
    now = bfs_que.front();//取带搜索队列中的队头
    visit[now.row][now.col] = 'S';
    bfs_que.pop();//取队头之后将队头pop出去
    while(!(now.row == 29 && now.col == 49)){//因为题目给的是有解的,我们这里就当未到终点时,一直搜索
        for(int i = 0; i < 4; i++){//按照字典序尝试四个方向是否可以走
            if(is_ok(now.row + next_dir[i][0],now.col + next_dir[i][1])){//如果这个方向的下一步可以走,就将它的信息加入待搜索队列
                ds mid = {now.row + next_dir[i][0],now.col + next_dir[i][1],dir[i]};//存入mid中
                bfs_que.push(mid);//将mid放入待搜索队列
            }
        }
        if(!(now.row == 29 && now.col == 49)){
            now = bfs_que.front();//取待搜索队列的队头
//            cout<<now.row<<" "<<now.col<<" "<<now.director<<" "<<bfs_que.size()<<endl;
            visit[now.row][now.col] = now.director;
            bfs_que.pop();//将队头pop
        } else
            break;
    }
}
int main(){
    fstream in;//文件流,这里面直接读取迷宫的txt文件
    in.open("/Users/qiguan/maze.txt");
    //读取文件
    for(int i = 0; i < 30; i++){
        for(int j = 0 ; j < 50; j++) {
            in >> maze[i][j];
        }
    }
    bfs();
    //D L R U的字典序对应的数组下标
    dir_index['D'] = 0;
    dir_index['L'] = 1;
    dir_index['R'] = 2;
    dir_index['U'] = 3;
    string ans = "";//用于存放路径
    int row = 29, col = 49;//从终点往起点回溯
    while(!(row == 0 && col == 0)){//回溯求解路径
        ans = ans + visit[row][col];
        char dir = visit[row][col];
        row = row - next_dir[dir_index[dir]][0];//减去来时候的路径
        col = col - next_dir[dir_index[dir]][1];
    }
    reverse(ans.begin(),ans.end());//得到的字符串进行逆序
    cout<<ans;//这就是需要的路径信息
    return 0;
}

答案为:
DDDDRRURRRRRRRDRRRDDDLDDRDDDDDDDDDDDDRDRDRRUUURRRRDDDDRDRRRRRURRRDRRDDDRRRRUURUUUUUUUULLLUUUURRRRUULLLUUUULLUUULUURRURRURURRRDRDRRRRDRDRDDLLLDDRRDDRDDLDDDLLDDLLLDLDDDLDDRRRRRRRRRDDDDDDRR
一共是走186步,答案输入这个字符串

试题 F: 特别数的和

时间限制: 1.0s 内存限制: 256.0MB 本题总分:15 分
【问题描述】
小明对数位中含有 2、0、1、9 的数字很感兴趣(不包括前导 0),在 1 到 40 中这样的数包括 1、2、9、10 至 32、39 和 40,共 28 个,他们的和是 574。
请问,在 1 到 n 中,所有这样的数的和是多少? 【输入格式】
输入一行包含两个整数 n。 【输出格式】
输出一行,包含一个整数,表示满足条件的数的和。
【样例输入】
40
【样例输出】
574
【评测用例规模与约定】
对于 20% 的评测用例,1 ≤ n ≤ 10。 对于 50% 的评测用例,1 ≤ n ≤ 100。 对于 80% 的评测用例,1 ≤ n ≤ 1000。 对于所有评测用例,1 ≤ n ≤ 10000。

试题F 题解:

这题只需要从1到n遍历,对每个数字求各个位置的数字,如果含有2、0、1、9其中任意一个,则加上他,最后输出结果。
代码为:

#include <iostream>
using namespace std;
bool is_ok(int num){
    while(num){
        int mid = num % 10;
        if(mid == 2 || mid == 0 || mid == 1 || mid ==9)
            return true;
        num /= 10;
    }
    return false;
}
int main(){
    int n,ans;
    ans = 0;
    cin>>n;
    for(int i = 1; i <= n; i++){
        if(is_ok(i)){
            ans += i;
        }

    }
    cout<<ans;
    return 0;
}

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

时间限制: 1.0s 内存限制: 256.0MB 本题总分:20 分
【问题描述】
给定一棵包含 N 个节点的完全二叉树,树上每个节点都有一个权值,按从 上到下、从左到右的顺序依次是 A1, A2, · · · AN,如下图所示:
现在小明要把相同深度的节点的权值加在一起,他想知道哪个深度的节点 权值之和最大?如果有多个深度的权值和同为最大,请你输出其中最小的深度。
注:根的深度是 1。 【输入格式】
第一行包含一个整数 N。 第二行包含N个整数A1,A2,··· AN。
【输出格式】
输出一个整数代表答案。
【样例输入】
7
1 6 5 4 3 2 1
【样例输出】
2
【评测用例规模与约定】
对于所有评测用例,1 ≤ N ≤ 100000,−100000 ≤ Ai ≤ 100000。

试题G 题解:

这题是让求完全二叉树中,和最大的层数,树的根深度为1。根据完全二叉树的特点,每一层的起始结点为2^(i-1),最后一个结点为 2^i -1。一个结点数为n的完全二叉树,深度h有:2^h -1 >= n,我们很容易可以求得h,然后计算每层的和即可。
代码为:

#include <iostream>
#include <cmath>
using namespace std;
int main(){
    int n,a[100005],ans,re;
    ans = -100005;//直接先赋最小值
    cin>>n;
    for(int i = 1; i <= n; i++)
        cin>>a[i];
    int h = 1;//二叉树的深度
    while(pow(2,h) < n +1 )
        h++;
    for(int i = 1; i <= h; i++){//求1 - h 层的最大值
        int mid = 0;
        int start = int(pow(2,i-1)),end = int(pow(2,i)-1);//每层节点从2^(i-1)到2^i -1
        for(int j =start; j <= end && j <= n;j++){
            mid += a[j];
        }
        if(mid > ans){//更新最大值,并记录层数
            ans = mid;
            re = i;
        }
    }
    cout<<re;
    return 0;
}

试题 H: 等差数列

时间限制: 1.0s 内存限制: 256.0MB 本题总分:20 分
【问题描述】
数学老师给小明出了一道等差数列求和的题目。但是粗心的小明忘记了一 部分的数列,只记得其中 N 个整数。
现在给出这 N 个整数,小明想知道包含这 N 个整数的最短的等差数列有 几项?
【输入格式】
输入的第一行包含一个整数 N。 第二行包含N个整数A1,A2,···,AN。(注意A1 ∼AN并不一定是按等差数
列中的顺序给出) 【输出格式】
输出一个整数表示答案。
【样例输入】
5
2 6 4 10 20
【样例输出】
10
【样例说明】
包含 2、6、4、10、20 的最短的等差数列是 2、4、6、8、10、12、14、16、 18、20。
【评测用例规模与约定】
对于所有评测用例,2 ≤ N ≤ 100000,0 ≤ Ai ≤ 10^9。

试题H 题解:

这题是求等差数列的最小项数,我们只需要求得绝对值最小的方差,就可以求出最小的项数,代码如下:

#include <iostream>
#include <cmath>
using namespace std;
int main(){
    int n,a[100005];
    int d = int(pow(10,9)+1);//方差d ,赋值最大值10^9 + 1
    cin>>n;
    for(int i = 0; i < n; i++)
        cin>>a[i];
    for(int i = 1; i < n; i++){
        int mid = abs(a[i] - a[i-1]);//找绝对值最小的方差d
        if(mid < d)
            d = mid;
    }
    int ans = ((a[n-1] - a[0]) / d ) + 1;
    cout<<ans;
    return 0;
}

试题 I: 后缀表达式

时间限制: 1.0s 内存限制: 256.0MB 本题总分:25 分
【问题描述】
给定 N 个加号、M 个减号以及 N + M + 1 个整数 A1, A2, · · · , AN+M+1,小 明想知道在所有由这 N 个加号、M 个减号以及 N + M + 1 个整数凑出的合法的 后缀表达式中,结果最大的是哪一个?
请你输出这个最大的结果。
例如使用1 2 3 + -,则 “2 3 + 1 -” 这个后缀表达式结果是 4,是最大的。
【输入格式】
第一行包含两个整数 N 和 M。
第二行包含 N + M + 1 个整数 A1, A2, · · · , AN+M+1。
【输出格式】
输出一个整数,代表答案。
【样例输入】
11 123
【样例输出】
4
【评测用例规模与约定】
对于所有评测用例,0 ≤ N, M ≤ 100000,−10^9 ≤ Ai ≤ 10^9。

试题I 题解:

这题我们要求的是这个有N个正数,M个负数的后缀表达式的最大值。在这N+M+1个数中,我们如果要想使用N个加,M个减使他的结果最大,则我们要使得加的时候优先加最大的正数,减的时候优先减最小的负数,那样的话,我们的总会就会最大。那么我们只需要将这N+M+1个数按照绝对值从大到小排列。然后从第一个数开始,如果第一个数为正,则我们使用加号,如果为负,则使用减号。由于我们有N+M+1个数,则我们可以使得有N+1个加号,因为有一个被加数,后面的数我们直接使用ANS来进行+/-即可,代码如下:

#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
bool cmp(int a, int b){
    return abs(a)>abs(b)? true: false;
}
int main(){
    int n,m,mid;
    long long ans = 0;
    vector<int> num;
    cin>>n>>m;
    for(int i = 0; i < n+m+1; i++){
        cin>>mid;
        num.push_back(mid);
    }
    sort(num.begin(),num.end(),cmp);//按照绝对值从大到小排序
    vector<int>::iterator it = num.begin();
    if(*it<0){//如果第一个数为负数,则我们使用一个减号,然后加上我们加的一个加号,否则消耗一个加号,M、N不需要变
        m++;
        n--;
    }
    ans = abs(*it);
    it++;
    for( ; it != num.end(); it++){
        if(*it >= 0){
            if(n){//有加号的时候,加正数。
                ans += *it;
                n--;
            } else{//加号用完之后只能减正数
                ans -= *it;
                m--;
            }
        } else{
            if(m){//有减号的时候 减负数
                ans -= *it;
                m--;
            } else{//没减号的时候 加负数
                ans += *it;
                n--;
            }
        }
    }
    cout<<ans;
    return 0;
}

试题 J: 灵能传输

时间限制: 1.0s 内存限制: 256.0MB 本题总分:25 分
【题目背景】
在游戏《星际争霸 II》中,高阶圣堂武士作为星灵的重要 AOE 单位,在 游戏的中后期发挥着重要的作用,其技能”灵能风暴“可以消耗大量的灵能对 一片区域内的敌军造成毁灭性的伤害。经常用于对抗人类的生化部队和虫族的 刺蛇飞龙等低血量单位。
【问题描述】
你控制着 n 名高阶圣堂武士,方便起见标为 1, 2, · · · , n。每名高阶圣堂武士 需要一定的灵能来战斗,每个人有一个灵能值 ai 表示其拥有的灵能的多少(ai 非负表示这名高阶圣堂武士比在最佳状态下多余了 ai 点灵能,ai 为负则表示这 名高阶圣堂武士还需要 −ai 点灵能才能到达最佳战斗状态)。现在系统赋予了 你的高阶圣堂武士一个能力,传递灵能,每次你可以选择一个 i ∈ [2, n − 1],若 ai ≥ 0 则其两旁的高阶圣堂武士,也就是 i − 1、i + 1 这两名高阶圣堂武士会从 i 这名高阶圣堂武士这里各抽取 ai 点灵能;若 ai < 0 则其两旁的高阶圣堂武士, 也就是 i − 1, i + 1 这两名高阶圣堂武士会给 i 这名高阶圣堂武士 −ai 点灵能。形 式化来讲就是 ai−1+ = ai, ai+1+ = ai, ai− = 2ai。
灵能是非常高效的作战工具,同时也非常危险且不稳定,一位高阶圣堂
武士拥有的灵能过多或者过少都不好,定义一组高阶圣堂武士的不稳定度为
maxn |ai|,请你通过不限次数的传递灵能操作使得你控制的这一组高阶圣堂武 i=1
士的不稳定度最小。

问题描述有部分数学符号显示不正确,下面看一下图片版的:

在这里插入图片描述
【输入格式】
本题包含多组询问。输入的第一行包含一个正整数 T 表示询问组数。 接下来依次输入每一组询问。
每组询问的第一行包含一个正整数 n,表示高阶圣堂武士的数量。 接下来一行包含n个数a1,a2,··· ,an。
【输出格式】
输出 T 行。每行一个整数依次表示每组询问的答案。 【样例输入】
3
3
5 -2 3
4
0 0 0 0
3
1 2 3
【样例输出】
3
0
3
【样例说明】
对于第一组询问:
对 2 号高阶圣堂武士进行传输操作后 a1 = 3,a2 = 2,a3 = 1。答案为 3。 对于第二组询问: 这一组高阶圣堂武士拥有的灵能都正好可以让他们达到最佳战斗状态。
【样例输入】
3
4
-1 -2 -3 7
4
2 3 4 -8
5
-1 -1 6 -1 -1
【样例输出】
5 7 4
【样例输入】
见文件trans3.in。
【样例输出】
见文件trans3.ans。
在这里插入图片描述

试题J 题解:

对这题目前没有一个好的方法,现在网上公布出来的也只有一个解题过程,那个代码也是错的,跑第三组样例和给的结果不一样,也就是说过不了10-15的样例组。

下面给出一个解决方法,这个方法同样给过不了10-15样例组,在相邻项交换可以,隔项交换调平就不可以了,大家可以参考下,然后这里题目提示说数据量大,需要用快速读取,也就是scanf。因为cin比scanf要慢很多,当我们数据很多的时候,就需要使用scanf进行读取,蓝桥杯的long long类型需要使用scanf("%l64d",&a)进行读取。

可以过前十组数据:

#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
#include <iterator>
#include <fstream>
using namespace std;
long long dp[3][305] ={0};
int max_n(int a,int b,int c){
    return a>=b&&a>=c ? a :( b >= c ? b :c );
}
bool cmp(int a, int b){
    return abs(a) > abs(b) ? true : false;
}
int main(){
    int t,n[3],ans[3],mid2;
    char z;
    cin>>t;
    for(int i = 0; i < t; i++){
        cin>>n[i];
        for(int j = 0; j < n[i]; j++){
            scanf("%l64d", &dp[i][j]);//蓝桥杯的long long需要用%l64d才能读
        }

    }
    for(int i = 0; i < t; i++){
            for(int j = 1; j < n[i] - 1; j++){
                while(max_n(abs(dp[i][j-1]+dp[i][j]),abs(-dp[i][j]),abs(dp[i][j+1]+dp[i][j])) < max_n(abs(dp[i][j-1]),abs(dp[i][j+1]),abs(dp[i][j+1]))){
                    dp[i][j-1] = dp[i][j-1] + dp[i][j];
                    dp[i][j+1] = dp[i][j+1] + dp[i][j];
                    dp[i][j] = -dp[i][j];
                }
        }
        sort(dp[i],dp[i]+n[i],cmp);
        ans[i] = abs(dp[i][0]);
    }
    for(int i = 0; i < t; i++)
        cout<<ans[i]<<endl;
    return 0;
}
发布了97 篇原创文章 · 获赞 50 · 访问量 8171

猜你喜欢

转载自blog.csdn.net/qq_43422111/article/details/103141393