• Triangle War POJ


    参考链接:https://www.cnblogs.com/nwpuacmteams/articles/5697873.html

    极小极大搜索 的个人理解(alpha-beta剪枝):https://www.cnblogs.com/Mathics/p/4100059.html

    代码+注释:

      1 #include<cstdio>
      2 using namespace std;
      3 
      4 //10个顶点之间的连线编号
      5 /*
      6 就比如下面这个矩阵的1,他所代表的边就是1号点与3号点的连线
      7 */
      8 int mat[11][11]=
      9 {
     10     {0,0,0,0,0,0,0,0,0,0,0},
     11     {0,0,0,1,0,0,0,0,0,0,0},
     12     {0,0,0,2,3,4,0,0,0,0,0},
     13     {0,1,2,0,0,5,6,0,0,0,0},
     14     {0,0,3,0,0,7,0,9,10,0,0},
     15     {0,0,4,5,7,0,8,0,11,12,0},
     16     {0,0,0,6,0,8,0,0,0,13,14},
     17     {0,0,0,0,9,0,0,0,15,0,0},
     18     {0,0,0,0,10,11,0,15,0,16,0},
     19     {0,0,0,0,0,12,13,0,16,0,17},
     20     {0,0,0,0,0,0,14,0,0,17,0}
     21 };
     22 
     23 //9个三角形组成的边状态压缩一下
     24 /*
     25 比如一个三角形是由1,2,3号边构成(这个边的编号我们在上卖弄的矩阵说过了)
     26 那么他们所压缩成的数是(1<<1)|(1<<2)|(1<<3)  ('|'是一种运算符号)
     27 */
     28 int tri[9]= {7,152,52,352,34304,3200,71680,12544,155648};
     29 int STATUS=(1<<18)-1;
     30 
     31 int Get_New_Status(int old,int edge,int &cnt) //在旧状态下改变后新的状态
     32 {
     33     int now=old|edge;
     34     for(int i=0;i<9;++i)
     35     {
     36         if((now&tri[i])==tri[i] && (old&tri[i])!=tri[i])
     37         {
     38             cnt++;
     39         }
     40     }
     41     return now;
     42 }
     43 
     44 int MaxSearch(int state,int alpha,int ca,int cb);
     45 int MinSearch(int state,int beta,int cnt_a,int cnt_b)  //当执行这个函数也就是该B方下棋
     46 {
     47     if(cnt_a==5) return 1;
     48     if(cnt_b==5) return -1;
     49     if(state==STATUS && cnt_a>cnt_b) return 1;
     50     else if(state==STATUS && cnt_a<cnt_b) return -1;
     51     int ans=1; //因为极小搜索要获取的是最小值(返回值只可能是1或-1,所以这里我们设为1就行)
     52     int remain=(~state)&STATUS;
     53     while(remain)
     54     {
     55         int edge=remain&(-remain);  //枚举每一条边
     56         int new_a=cnt_a,new_b=cnt_b;
     57         int now=Get_New_Status(state,edge,new_b),temp;
     58         if(new_b>cnt_b)
     59             temp=MinSearch(now,beta,cnt_a,new_b);  //返回值是1代表A获胜,否则B获胜
     60         else temp=MaxSearch(now,ans,cnt_a,new_b); //只不过Maxsearch会尽可能返回大值,Minsearch尽可能返回小值
     61         /*
     62         上面传参传的ans,这个参数的目的是用来限制对于B这一步棋无谓的搜索,他代表的意思是
     63         B所以的着法中,那个最好的着法的得分
     64 
     65         因为B是得分越小越有可能赢(A与其相反)
     66 
     67         比如这个时候B传过去一个1,然后对于B这一步得下一步得第一次试探,就返回一个-1,也就是说B赢了,那么不用
     68         进行B这一步得下一步得第二次第三次或更多次试探
     69 
     70         其实你的思想不用去不停的递归,看一层就可以
     71         */
     72         if(temp<ans) ans=temp;
     73         if(temp<=beta) return ans;
     74         remain-=edge;
     75     }
     76     return ans;
     77 }
     78 
     79 int MaxSearch(int state,int alpha,int ca,int cb)
     80 {
     81     //出现5个三角形,胜负已分
     82     if(ca>=5) return 1;
     83     if(cb>=5) return -1;
     84     //所有的边都取了,游戏也结束
     85     if(state==STATUS) return ca>cb?1:-1;
     86     int ans=-1;
     87     int remain=(~state)&STATUS;  //剩下还有哪些边可以取
     88     while(remain)
     89     {
     90         /*
     91         & 是 按位与运算符
     92         -x 是x 的补码;补码为取反+1
     93         x&(-x)就是取出来x二进制形式下的最小位权那个1
     94         */
     95         int seg=remain&(-remain); //枚举
     96 
     97         int ta=ca,tb=cb;
     98         int now=Get_New_Status(state,seg,ta),tmp;
     99         //是否有新的三角形生成
    100         if(ta>ca) tmp=MaxSearch(now,alpha,ta,cb);
    101         else tmp=MinSearch(now,ans,ta,cb);
    102         if(tmp>ans) ans=tmp;
    103         //alpha剪枝
    104         if(tmp>=alpha) return ans;
    105         remain-=seg;
    106     }
    107     return ans;
    108 }
    109 
    110 int main()
    111 {
    112     int t,cas=0;
    113     scanf("%d",&t);
    114     while(t--)
    115     {
    116         int n,u,v;
    117         scanf("%d",&n);
    118         //已经走了多少步,当前边的状态
    119         int cnt=0,state=0;
    120         //两个人分别有几个三角形
    121         int ca=0,cb=0;
    122         while(n--)
    123         {
    124             scanf("%d%d",&u,&v);
    125             int ta=ca,tb=cb;
    126             state=Get_New_Status(state,1<<mat[u][v],(cnt&1)?cb:ca);
    127             //没有新的三角形,
    128             if(ta==ca&&tb==cb)
    129                 cnt++;
    130         }
    131         int ans;
    132         /*
    133         当调用依次MinSearch或者MaxSearch函数的时候,其实他已经把这个局势下所有情况都试了一遍
    134         同时因为题目上没有说平局输出什么,所以我们也不需要去管(其实也可以管,加一个判断就可以)
    135         */
    136         if(cnt&1)
    137             ans=MinSearch(state,-1,ca,cb);
    138         else
    139             ans=MaxSearch(state,1,ca,cb);
    140 
    141         printf("Game %d: %c wins.
    ",++cas,ans==1?'A':'B');
    142     }
    143     return 0;
    144 }
  • 相关阅读:
    对返回的json数据重写格式,用特性JsonConverter
    dev 的NavBarControl动态菜单
    获取oracel数据库的结构
    Java-背单词程序(俄语)
    实现同或操作 C++
    输入字符串先用cin后用getline函数失效原因
    C++全局变量与局部变量
    4.Redis事务
    3.持久化配置
    2.常用数据类型
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/12885006.html
Copyright © 2020-2023  润新知