h
10.14
思路:
alpha-beta剪枝的经典应用
学习了一发可以参照这篇blog
#include <cstdio>
#include <iostream>
#include <algorithm>
#define N 25
#define inf 0x3f3f3f3f
using namespace std;
const int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int n, m;
int mp[N][N];
int dfs(int step, int player, int alpha, int beta, int fx, int fy, int px, int py){
int ans, val, flag = 0;
if(player == 1) ans = beta; //1想尽量让自己得高分,但是它的上一层2想让它得低分
else ans = alpha;
for(int d=0; d<4; d++){
int x = fx + dx[d], y = fy + dy[d];
if(x && x<=n && y && y<=m && mp[x][y]==0){
flag = true;
mp[x][y] = player;
if(player == 1) val = dfs(step+1, 2, alpha, ans, px, py, x, y);
else val = dfs(step+1, 1, ans, beta, px, py, x, y);
mp[x][y] = 0;
if(player == 2 && val <= beta) return beta;
//它的上一层要取最大值,而且已经有了一个选项是beta(最不济也能取到beta)
//而这一层要取最小值,而且已经有了一个选项是val,如果之后的选项大于val,我们就选val
//也就是说我们所选的值一定小于等于val,也就小于等于beta,那么在上一层决策的时候就一定选deta而不是val
//这样一来我们当前这一个局面就没有任何的贡献,自然可以return了
if(player == 1 && val >= alpha) return alpha;
if(player == 1) ans = max(ans, val);
else ans = min(ans, val);
}
}
if( !flag ){
if(player == 1) return step - 60;
else return 60 - step;//以正负区分输赢 ans小于50
}
return ans;
}
int main(){
freopen("h.in", "r", stdin);
freopen("h.out", "w", stdout);
scanf("%d%d", &n, &m);
int stx, sty, edx, edy;
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++){
scanf("%d", &mp[i][j]);
if(mp[i][j] == 1) stx = i, sty = j;
if(mp[i][j] == 2) edx = i, edy = j;
}
int ans = dfs(1, 1, inf, -inf, stx, sty, edx, edy);
if(ans > 0) printf("1 %d\n", 60 - ans);
else printf("2 %d\n", 60 + ans);
return 0;
}