CodeForces-Game with Marbles (Easy Version) 转存洛谷
题目
题目分析
看到数据很小,( $ 2 \le n \le 6 $ ),考虑直接暴力深搜。
-
如果是甲所选,他会将 \(a_i\) 减一且 \(b_i\) 变为 \(0\)。
-
如果是乙所选,他会将 \(b_i\) 减一且 \(a_i\) 变为 \(0\)。
-
\(A=\sum_{p=1}^{n}a_p\ , \ B=\sum_{p=1}^{n}b_p\)。
甲想让 \(A-B\) 越大越好,乙想让 \(A-B\) 越小越好,如果甲乙足够聪明,那么最后 \(A-B\) 的值为多少?
就是一个博弈论,双方所做的决策当前都是最优的才行,对于某一个时刻,说明下该操作的贡献,比如某刻甲来做决定,将 \(b_i\) 变为 \(0\),同时自身减一,所以贡献是 \(a_i-1\)。
题目思路
这道题的数据很小,但是在用深搜枚举的时候,并不是简简单单的一层一层往下搜索,因为这里是要满足双方两人的最优选法,所以这里的深搜写法应该是在搜同一层时找到当前最优解,使用该最优解去对前一层进行处理。
甲的先选,然后乙选,既然用搜索就不要考虑什么贪心了,直接开始搜,来个循环对甲的数组一个个遍历然后使用搜索,然后搜过的要用判重数组记录好,注意好回溯就行。
由于是博弈论,我们必须保证每一次搜索对于该阶段选的人最优,所以我们必须使用一个变量来记录当前最优值,所以需要使用 \(\max\) 函数。
得到那个最优的答案,返回到上一层,就这样不断深搜到最后一层,找到了最优答案返回,一直返回到第一层,就这样就好了。
代码实现
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
int vis[10];
int n;
struct node {
ll x, y;
} ;
node a[10];
ll LTE(int step) {
if (step == n + 1)return 0;
ll HS = -9e18 + 1;
for (int i = 1; i <= n; i++) {
if (vis[i])continue;
if (step % 2 == 1) {
vis[i] = 1;
ll optimal=LTE(step+1);
HS = max(HS, a[i].x - 1 - optimal);
vis[i] = 0;
} else {
vis[i] = 1;
ll optimal=LTE(step+1);
HS = max(HS, a[i].y - 1 - optimal);
vis[i] = 0;
}
}
return HS;
}
int main() {
int t;
cin >> t;
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
while (t--) {
memset(vis, 0, sizeof vis);
memset(a, 0, sizeof a);
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i].x;
for (int i = 1; i <= n; i++)
cin >> a[i].y;
cout << LTE(1) << endl;
}
return 0;
}