Educational Codeforces Round 138 (Rated for Div. 2) C. Number Game 解题报告

原题链接:

Problem - C - Codeforces

题目描述:

Alice and Bob are playing a game. They have an array of positive integers aa of size nn.

Before starting the game, Alice chooses an integer k≥0k≥0. The game lasts for kk stages, the stages are numbered from 11 to kk. During the ii-th stage, Alice must remove an element from the array that is less than or equal to k−i+1k−i+1. After that, if the array is not empty, Bob must add k−i+1k−i+1 to an arbitrary element of the array. Note that both Alice's move and Bob's move are two parts of the same stage of the game. If Alice can't delete an element during some stage, she loses. If the kk-th stage ends and Alice hasn't lost yet, she wins.

Your task is to determine the maximum value of kk such that Alice can win if both players play optimally. Bob plays against Alice, so he tries to make her lose the game, if it's possible.

Input

The first line contains a single integer tt (1≤t≤1001≤t≤100) — the number of test cases.

The first line of each test case contains a single integer nn (1≤n≤1001≤n≤100) — the size of the array aa.

The second line contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤n1≤ai≤n).

Output

For each test case, print one integer — the maximum value of kk such that Alice can win if both players play optimally.

题目大意:

给定n个数,游戏规则如下:在开始游戏之前,Alice选择一个整数k≥0。游戏进行k回合,每一回合开始Alice先选择一个小于等于k-i+1的数,将其删除,然后Bob选择一个数加上k-i+1,一回合结束,如果Alice在某个阶段无法删除元素,她将失败。如果第k阶段结束,爱丽丝还没有输,她就赢了。请问两边都选择最优策略时,要保证Alice胜利,k最大可以为多少?

解题思路:

最优策略很明显:每回合Alice选择当前能删除的最大的数,而Bob则选择当前最小的数给其加上k-i+1,我们可以看到,题目给出的数据非常的小,而且时间限制也给的很宽,所以我们完全可以从大到小暴力枚举k,模拟两人的最优策略,具体细节参考代码。

代码(CPP):

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 110;
const int INF = 0x3fffffff;
int n, vis[maxn], a[maxn];

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cout << fixed;
    cout.precision(18);

    int t;
    cin >> t;
    while (t--)
    {
        cin >> n;
        for (int i = 1; i <= n; i++)
            cin >> a[i];

        // 枚举找最大的k
        for (int k = n; k >= 0; k--)
        {
            bool flag = true;
            memset(vis, 0, sizeof vis);
            // 游戏进行k个回合
            for (int i = 1; i <= k; i++)
            {
                int mx = 0, x = -1, y = -1;
                // Alice的最优策略是找到当前能删除的最大数(小于等于k-i+1的最大的数)
                for (int j = 1; j <= n; j++)
                {
                    if (!vis[j] && a[j] <= k - i + 1 && a[j] > mx)
                    {
                        mx = a[j];
                        x = j;
                    }
                }
                // 如果这一轮Alice没有能够删除的数,则Alice失败
                if (x == -1)
                {
                    flag = false;
                    break;
                }
                // 找到能删除的最大的数了,删除掉
                vis[x] = true;
                // Bob的最优策略是找到最小的数字加上k-i+1
                int mn = 110;
                for (int j = 1; j <= n; j++)
                {
                    if (!vis[j] && a[j] < mn)
                    {
                        mn = a[j];
                        y = j;
                    }
                }
                if(y != -1)
                    vis[y] = true; // 等价于a[y] += k = i + 1;
            }
            if (flag)  // Alice胜利
            {
                cout << k << endl;
                break;
            }
        }
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值