[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.
", _++, ret == 1 ? 'A' : 'B');
118     }
119     return 0;
120 }
原文地址:https://www.cnblogs.com/kirai/p/6476282.html