poj 1085 Triangle War 博弈论+记忆化搜索

思路:总共有18条边,9个三角形。

极大极小化搜索+剪枝比较慢,所以用记忆化搜索!!

用state存放当前的加边后的状态,并判断是否构成三角形,找出最优解。

代码如下:

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<algorithm>
 4 #include<iomanip>
 5 #include<cmath>
 6 #include<cstring>
 7 #include<vector>
 8 #define inf 1<<25
 9 using namespace std;
10 int edge[][2]={{1,2},{1,3},{2,3},{2,4},{2,5},{3,5},{3,6},{4,5},{5,6},{4,7},{4,8},{5,8},{5,9},{6,9},{6,10}
11 ,{7,8},{8,9},{9,10}};
12 int tri[][3]={{0,1,2},{3,4,7},{2,4,5},{5,6,8},{9,10,15},{7,10,11},{11,12,16},{8,12,13},{13,14,17}};
13 int p[18],dp[1<<18];
14 int cal(int state,int e)
15 {
16       int ans=0;
17       for(int i=0;i<9;i++){
18             bool flag=0;
19             for(int j=0;j<3;j++) //判断边e是否在这个三角形中
20                   if(e==tri[i][j]) flag=true;
21             if(flag){ //e在这个三角形中
22                   for(int j=0;j<3;j++){
23                         if(!(p[tri[i][j]]&state||e==tri[i][j])){ //如果满足条件说明tri[i][j]这条边不存在且e也不是这条边
24                               ans--;break;                               //也就是不能构成三角形,否则能构成
25                         }
26                   }
27                   ans++;
28             }
29       }
30       return ans;
31 }
32 int dfs(int state)
33 {
34       if(dp[state]!=-inf) return dp[state];
35       int ans=-inf;
36       for(int i=0;i<18;i++){
37             if(!(state&p[i])){
38                   int tt=cal(state,i);
39                   if(tt) tt+=dfs(state|p[i]);
40                   else tt-=dfs(state|p[i]);
41                   ans=max(ans,tt);
42             }
43       }
44       return dp[state]=ans;
45 }
46 int main()
47 {
48       //freopen("1.txt","r",stdin);
49     int t,u,v,ca=0,m;
50     p[0]=1;
51     for(int i=1;i<18;i++) p[i]=p[i-1]*2;
52     for(int i=0;i<(1<<18);i++) dp[i]=-inf;
53     dp[(1<<18)-1]=0;
54     scanf("%d",&t);
55     while(t--){
56             scanf("%d",&m);
57             int m0=0,m1=0,tt=0,state=0,side=0;
58             while(m--){
59                   scanf("%d%d",&u,&v);
60                   for(int i=0;i<18;i++)
61                         if(edge[i][0]==u&&edge[i][1]==v){
62                               tt=cal(state,i);
63                               state|=p[i];
64                               side==0?m0+=tt:m1+=tt;
65                               side++;
66                               if(tt) side++;
67                               side%=2;
68                               break;
69                         }
70             }
71             int ans=m0-m1;
72             if(side==0) ans+=dfs(state);
73             else ans-=dfs(state);
74             printf("Game %d: %s
",++ca,ans>0?"A wins.":"B wins.");
75     }
76     return 0;
77 }
View Code
原文地址:https://www.cnblogs.com/xin-hua/p/3327988.html