zoukankan      html  css  js  c++  java
  • [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 }
  • 相关阅读:
    利用Turtle绘制各种图形
    turtle库元素语法分析
    python中input()函数与print()函数
    python代码编写规范
    如何将python下载源地址修改为国内镜像源
    探秘AutoCAD中的组
    ObjectARX开发教程(转)——第2课:AutoCAD数据库
    ObjectARX开发教程(转)——第1课:概述
    探秘AutoCAD中的标注关联
    AutoCAD快速开发框架之日志Logging
  • 原文地址:https://www.cnblogs.com/kirai/p/6476282.html
Copyright © 2011-2022 走看看