蓝桥杯2023年第十四届省赛真题-三国游戏

题目来自Dotcpp网站:

对题目分析:

①我们要注意数据读入的问题,它的一行表示An。

②题目要求我们如果有一个国家获胜,要求出最多发生了多少个事件。

暴力思路:

我们可以用DFS 选和不选 的思想,对事件枚举。当 DFS 要返回时,可以先for循环遍历一下,统计一下st数组中 == 1 的个数,这就是发生的总事件。然后在判断一下,这三个国家中有没有一个国家获胜,如果获胜了,就和我们统计的总事件来比较,保证返回的总事件是最大的。最后,输出前判断一下要不要输出 -1 。

DFS代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5+10;

int n;
int a[N], b[N], c[N], st[N];
//如果有其中一个国家获胜
//最多发生了多少个事件 要得到最大值
int smax = -1;
//用一个数组记录x,y,z的士兵数量
//1表示x 2表示y 3表示z
int arr[3];

void dfs(int x){
    if(x > n){
        //记录选的情况 
        int cnt2 = 0;
        for(int i = 1; i <= n; i++){
            if(st[i] == 1){
                cnt2 += 1;
            }
        }
        //得到它们三个之间的最大值 来判断游戏有没有结束
        //要得到他们三个之间最大的那个下标
        int cnt = 1;
        for(int i = 1; i <= 3; i++){
            if(arr[cnt] < arr[i]){
                cnt = i;
            }
        }
        //判断游戏能不能结束
        int sum = 0;
        for(int i = 1; i <= 3; i++){
            sum += arr[i];
        }
        if(arr[cnt] > sum - arr[cnt]){
            smax = max(smax, cnt2);
        }
        return;
    }
    
    //选
    st[x] = 1;
    arr[1] += a[x];
    arr[2] += b[x];
    arr[3] += c[x];
    dfs(x+1);
    arr[1] -= a[x];
    arr[2] -= b[x];
    arr[3] -= c[x];
    st[x] = 0;
    
    //不选
    st[x] = 2;
    dfs(x+1);
    st[x] = 0;
}

signed main(){
    //读入数据
    cin >> n;
        for(int i = 1; i <= n; i++){
        cin >> a[i];
    }
    for(int i = 1; i <= n; i++){
        cin >> b[i];
    }
    for(int i = 1; i <= n; i++){
        cin >> c[i];
    }
    
    dfs(1);
    
    cout << smax;
    return 0;
}

由于直接暴力,然后题目的数据量很大,这样做的话会超时,因此我们要优化。

贪心思路:

①由于题目中告诉我们游戏中只有三个国家,所以我们一次假设其中一个国家获胜。我们可以用一个数组来存储每次事件的情况。(可能大于0 也可能小于0)。

②当我们假设 x 国家获胜,就有:d[x] = x-(y+z),之后对 d 数组排序,定义一个sum,每次选择最大值,用sum统计选择的次数,sum表示的当x国家获胜的时候,最多选择了多少个事件。对于 y,z国家依次用数组来记录选择事件之后的答案。

贪心代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5+10;

int n;
int a[N], b[N], c[N];

int cal(int a[], int b[], int c[], int d[]){
    for(int i = 1; i <= n; i++){
        d[i] = a[i] - (b[i] + c[i]);
    }
    //要降序排序
    sort(d+1, d+1+n);
    reverse(d+1, d+1+n);
    int sum = 0;
    int cnt = 0;
    for(int i = 1; i <= n; i++){
        if(d[i] + sum > 0){
            sum += d[i];
            cnt += 1;
        }else{
            break;
        }
    }
    return cnt;
}

signed main(){
    //读入数据
    cin >> n;
    for(int i = 1; i <= n; i++){
        cin >> a[i];
    }
    for(int i = 1; i <= n; i++){
        cin >> b[i];
    }
    for(int i = 1; i <= n; i++){
        cin >> c[i];
    }
    int d[N];
    int ans = -1;
    //x国家获胜
    ans = max(ans, cal(a, b, c, d));
    // y 国家获胜
    ans = max(ans, cal(b,a,c,d));
    //z国家获胜
    ans = max(ans, cal(c, a, b, d));
    
    cout << ans <<endl;
    
    return 0;
}

贴一篇大佬的贪心思路