[POJ1085]Triangle War(极大极小搜索,alpha-beta剪枝)
题目链接:http://poj.org/problem?id=1085
α-β剪枝的wiki:https://zh.wikipedia.org/wiki/Alpha-beta%E5%89%AA%E6%9E%9D
参考了这篇博客:http://blog.csdn.net/dooder_daodao/article/details/6682971
题意:两个人轮流在九个小正三角形组成的大三角形上面选取边,如果当前选择的边刚好为某些三角形最后一个未选取的边,则该玩家得分为这些三角形数目,如果当前玩家取得三角形,则可以得到另一个机会选择。
我们面对的则是给定了一个初始的局面,要我们进行下去。假设都采取最优策略,问最终谁会获胜。
首先面对的问题是给线和三角形做一个映射,直接搬。
接下来模拟给的步骤,构造当前的局面,get函数很巧妙,直接枚举9个三角形的状态,当前状态cur=上一个状态pre与当前选定的pos或,看看tri中有没有在cur里出现,有的话说明多了一个三角形,则便多了一个机会。
可以发现一共有9个三角形,那么只要拿到>=5个则一定会获胜。
接下来就是极大极小搜索,假设主人公是a,对手是b。则偶数是a行动,a希望值尽可能大,b希望尽可能小。
根据先后手不同情况遍历a(或者b,后面默认a先走啦)的每一种走法,在之前遍历的a的每一种走法的基础上,遍历b的所有走法。。直到分出胜负或者无路可走,无路可走返回当前统计的结果。
1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <climits> 6 #include <complex> 7 #include <cassert> 8 #include <cstdio> 9 #include <bitset> 10 #include <vector> 11 #include <deque> 12 #include <queue> 13 #include <stack> 14 #include <ctime> 15 #include <set> 16 #include <map> 17 #include <cmath> 18 using namespace std; 19 20 const int maxn = 15; 21 const int FULL = (1 << 18) - 1; 22 int n; 23 int a, b; 24 int G[maxn][maxn]; 25 int mat[11][11] = { 26 {0,0,0,0,0,0,0,0,0,0,0}, 27 {0,0,0,1,0,0,0,0,0,0,0}, 28 {0,0,0,2,3,4,0,0,0,0,0}, 29 {0,1,2,0,0,5,6,0,0,0,0}, 30 {0,0,3,0,0,7,0,9,10,0,0}, 31 {0,0,4,5,7,0,8,0,11,12,0}, 32 {0,0,0,6,0,8,0,0,0,13,14}, 33 {0,0,0,0,9,0,0,0,15,0,0}, 34 {0,0,0,0,10,11,0,15,0,16,0}, 35 {0,0,0,0,0,12,13,0,16,0,17}, 36 {0,0,0,0,0,0,14,0,0,17,0} 37 }; 38 /* 39 tri[0]=1|(1<<1)|(1<<2); 40 tri[1]=(1<<3)|(1<<4)|(1<<7); 41 tri[2]=(1<<2)|(1<<4)|(1<<5); 42 tri[3]=(1<<5)|(1<<6)|(1<<8); 43 tri[4]=(1<<9)|(1<<10)|(1<<15); 44 tri[5]=(1<<7)|(1<<10)|(1<<11); 45 tri[6]=(1<<11)|(1<<12)|(1<<16); 46 tri[7]=(1<<8)|(1<<12)|(1<<13); 47 tri[8]=(1<<13)|(1<<14)|(1<<17); 48 */ 49 int tri[maxn] = {7,152,52,352,34304,3200,71680,12544,155648}; 50 int sta, cnt; 51 52 int Max(int sta, int alpha, int a, int b); 53 int Min(int sta, int beta, int a, int b); 54 55 int get(int pre, int pos, int& cnt) { 56 int cur = pre | pos; 57 for(int i = 0; i < 9; i++) { 58 if((pre & tri[i]) != tri[i] && (cur & tri[i]) == tri[i]) cnt++; 59 } 60 return cur; 61 } 62 63 int Max(int sta, int alpha, int a, int b) { 64 if(a >= 5) return 1; 65 if(b >= 5) return -1; 66 if(sta == FULL) return a > b ? 1 : -1; 67 int ret = -1; 68 int remain = (~sta) & FULL; 69 while(remain) { 70 int pos = remain & (-remain); 71 int ta = a; 72 int cur = get(sta, pos, ta); 73 int tmp = (ta > a) ? Max(cur, alpha, ta, b) : Min(cur, ret, ta, b); 74 ret = max(ret, tmp); 75 if(tmp >= alpha) return ret; 76 remain -= pos; 77 } 78 return ret; 79 } 80 81 int Min(int sta, int beta, int a, int b) { 82 if(a >= 5) return 1; 83 if(b >= 5) return -1; 84 if(sta == FULL) return a > b ? 1 : -1; 85 int ret = 1; 86 int remain = (~sta) & FULL; 87 while(remain) { 88 int pos = remain & (-remain); 89 int tb = b; 90 int cur = get(sta, pos, tb); 91 int tmp = (tb > b) ? Min(cur, beta, a, tb) : Max(cur, ret, a, tb); 92 ret = min(ret, tmp); 93 if(tmp <= beta) return ret; 94 remain -= pos; 95 } 96 return ret; 97 } 98 99 int main() { 100 // freopen("in", "r", stdin); 101 int T, _ = 1; 102 int u, v; 103 scanf("%d", &T); 104 while(T--) { 105 a = 0, b = 0; 106 cnt = 0, sta = 0; 107 scanf("%d", &n); 108 for(int i = 0; i < n; i++) { 109 scanf("%d %d", &u, &v); 110 int ta = a, tb = b; 111 sta = get(sta, 1<<mat[u][v], (cnt&1)?b:a); 112 if(ta == a && tb == b) cnt++; 113 } 114 int ret = 0; 115 if(cnt & 1) ret = Min(sta, -1, a, b); 116 else ret = Max(sta, 1, a, b); 117 printf("Game %d: %c wins.\n", _++, ret == 1 ? 'A' : 'B'); 118 } 119 return 0; 120 }