2017 ICPC Naning I. Rake It In(alpha-beta剪枝)
阿新 • • 發佈:2019-02-13
題意: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;
}