思路:总共有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\n",++ca,ans>0?"A wins.":"B wins."); 75 } 76 return 0; 77 }