原题地址:https://nanti.jisuanke.com/t/19975
题意:Alice和Bob在玩一种名为“Rake It In”的游戏,起初有一个44的棋盘,每一格为一个1~10的整数,两人轮流行动,各自k次,行动者选择棋盘中某一个22的区域,将这四个元素求和,加到最终答案中,并将四个元素按逆时针旋转90度,Alice先行。Alice的目标是最大化最后的答案,Bob相反。请写一个程序计算,在两人都最聪明的情况下,最终答案为多少。
思路:直接DFS容易卡常,正解应该是加alpha-beta 剪枝.
附上有无剪枝的区别:
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#define fuck(x) cout<<#x<<" = "<<x<<endl;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 100086;
const int inf = 2.1e9;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
int mp[5][5], ans;
int k;
inline void chang(int x, int y) {//旋转
ans += mp[x][y];
ans += mp[x + 1][y];
ans += mp[x][y + 1];
ans += mp[x + 1][y + 1];
int t = mp[x][y];
mp[x][y] = mp[x][y + 1];
mp[x][y + 1] = mp[x + 1][y + 1];
mp[x + 1][y + 1] = mp[x + 1][y];
mp[x + 1][y] = t;
}
inline void huisu(int x, int y) {//再旋转回来
ans -= mp[x][y];
ans -= mp[x + 1][y];
ans -= mp[x][y + 1];
ans -= mp[x + 1][y + 1];
int t = mp[x][y];
mp[x][y] = mp[x + 1][y];
mp[x + 1][y] = mp[x + 1][y + 1];
mp[x + 1][y + 1] = mp[x][y + 1];
mp[x][y + 1] = t;
}
int dfs(int t, int alpha, int beta) {
if (t > 2 * k) {
return ans;
}
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
chang(i, j);
if (t & 1) {
int cnt = dfs(t + 1, alpha, beta);
alpha = alpha > cnt ? alpha : cnt;
huisu(i, j);
} else {
int cnt = dfs(t + 1, alpha, beta);
beta = beta > cnt ? cnt : beta;
huisu(i, j);
}
if (beta <= alpha) return t & 1 ? alpha : beta;//alpha-beta 剪枝
}
}
return t & 1 ? alpha : beta;
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%d", &k);
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= 4; j++) {
scanf("%d", &mp[i][j]);
}
}
ans = 0;
printf("%d\n", dfs(1, -INF, INF));
}
return 0;
}