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\n",++ca,ans>0?"A wins.":"B wins.");

75     }

76     return 0;

77 }
View Code

 

 

 

你可能感兴趣的:(poj)