Triangle War--POJ 1085

1、题目类型:博弈、DP。

2、解题思路:(1)构建18条边、9个三角形分别由那三条边组成;(2)模拟输入的残局,并记录A、B获得三角形的差值,中间利用player保持A、B主动权的变换;(3)DP递归剩余情况,寻找player到最后的单步最有情况;(4)判断最终的最大差值MAX,正负即A、B博弈的结果。

3、注意事项:注意构造三角形三边是对应的16进制表示;DP递归过程中注意dp[]的更新。

4、参考博客:http://blog.csdn.net/bobten2008/archive/2009/08/25/4484005.aspx

5、实现方法:

#include<iostream>
#include
<algorithm>
using namespace std;
#define MIN -10

int line[18][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},
{
7,8},{8,9},{9,10}
};

int tri[9][3]={
{
0x01,0x02,0x04},
{
0x04,0x10,0x20},
{
0x08,0x10,0x80},
{
0x20,0x40,0x100},
{
0x200,0x400,0x8000},
{
0x80,0x400,0x800},
{
0x800,0x1000,0x10000},
{
0x100,0x1000,0x2000},
{
0x2000,0x4000,0x20000}
};

int dp[600000],pow[18];
int m,player,state,x,y;

//寻找当前状况下,是否可以构成三角形
int Cal(int pos,int state)
{
int i,j,flag,t,get=0;
for(i=0;i<9;i++)
{
flag
=0;t=3;
for(j=0;j<3;j++)
{
if(pow[pos]&tri[i][j])
t
=j;
else if(state&tri[i][j])
flag
++;
}
if(t==3)
continue;
if(flag==2)
++get;
}
return get;
}

int DP(int state)
{
if(dp[state]!=MIN)
return dp[state];
int i,t,MAX=MIN;
for(i=0;i<18;i++)
{
if(!(state&pow[i]))
{
t
=Cal(i,state);
t
+=(t>0?1:-1)*DP(state|pow[i]);
MAX
=(t>MAX?t:MAX);
}
}
dp[state]
=MAX;
return MAX;
}

void Solve(int ca)
{
int i,j,t,cnt=0;
cin
>>m;
player
=1;
state
=0;
for(i=0;i<m;i++)
{
cin
>>x>>y;
for(j=0;j<18;j++)
{
if(x==line[j][0] && y==line[j][1])
{
t
=Cal(j,state);
state
|=pow[j];
break;
}
}
if(t)
cnt
+=player*t;
else
player
*=-1;
}
cout
<<"Game "<<ca<<": "<<((cnt+player*DP(state))>0?'A':'B')<<" wins."<<endl;
}

int main()
{
int i,T,tmp=1;
cin
>>T;
for(i=0;i<18;i++)
{
pow[i]
=tmp;
tmp
*=2;
}
fill(dp,dp
+600000,-10);
dp[
0x3FFFF]=0;
for(i=1;i<=T;i++)
{
Solve(i);
}
return 0;
}

 

posted @ 2010-09-25 21:39  勇泽  阅读(740)  评论(0编辑  收藏  举报