标签:
http://acm.hdu.edu.cn/showproblem.php?pid=4753



1 15 1 2 1 5 2 6 5 9 6 10 9 10 5 6 2 3 3 7 7 11 10 11 3 4 6 7 7 8 4 8
Case #1: Tom200HintIn case 1, Tom200 gets two points when she add edge 5 -> 6, two points in edge 6 -> 7, one point in 4 -> 8.
/**
hdu4753 状态压缩dp博弈(记忆化搜索写法)
题目大意:为一个3*3的棋盘连边(如图所示)加上当前边后多了几个格子四条边都被填上了,就得几分,现在tom和jerry交替填边,总是tom先,
现在已经填了n条边了,问剩下的边二者都采取最优的策略,谁会赢
解题思路:由于未知的边最多只有12条,我们可以采取状态压缩,用搜索的方式写
注意:不可以直接压24位,会爆内存的
*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
int mp[24][24];///给每条边进行编号
int vis[25];///标记是否已经访问过该边
int dp[(1<<13)+3],cnt,x[25];
int tom,jerry,n;
int circle[9][4]={///对应的9个格子各自的四条边
1,4,5,8,
2,5,6,9,
3,6,7,10,
8,11,12,15,
9,12,13,16,
10,13,14,17,
15,18,19,22,
16,19,20,23,
17,20,21,24
};
void init()
{
memset(mp,0,sizeof(mp));
mp[1][2]=1,mp[2][3]=2,mp[3][4]=3;
mp[1][5]=4,mp[2][6]=5,mp[3][7]=6,mp[4][8]=7;
mp[5][6]=8,mp[6][7]=9,mp[7][8]=10;
mp[5][9]=11,mp[6][10]=12,mp[7][11]=13,mp[8][12]=14;
mp[9][10]=15,mp[10][11]=16,mp[11][12]=17;
mp[9][13]=18,mp[10][14]=19,mp[11][15]=20,mp[12][16]=21;
mp[13][14]=22,mp[14][15]=23,mp[15][16]=24;
}
int judge()
{
int sum=0;
for(int i=0;i<9;i++)
{
if(vis[circle[i][0]]&&vis[circle[i][1]]&&vis[circle[i][2]]&&vis[circle[i][3]])
sum++;
}
return sum;
}
int ok(int ste,int k)
{
int vv[25];
memset(vv,0,sizeof(vv));
for(int i=0;i<=cnt;i++)
{
if(ste&(1<<i))
vv[x[i]]=1;
}
int s1=0,s2=0;
for(int i=0;i<9;i++)
{
if((vis[circle[i][0]]||vv[circle[i][0]])&&(vis[circle[i][1]]||vv[circle[i][1]])&&(vis[circle[i][2]]||vv[circle[i][2]])&&(vis[circle[i][3]]||vv[circle[i][3]]))
s1++;
}
vv[x[k]]=1;
for(int i=0;i<9;i++)
{
if((vis[circle[i][0]]||vv[circle[i][0]])&&(vis[circle[i][1]]||vv[circle[i][1]])&&(vis[circle[i][2]]||vv[circle[i][2]])&&(vis[circle[i][3]]||vv[circle[i][3]]))
s2++;
}
return s2-s1;
}
int dfs(int ste,int k)
{
if(dp[ste]!=-1)return dp[ste];
int maxx=0;
for(int i=0;i<=cnt;i++)
{
int s=1<<i;
if((s&ste)==0)
{
s=ste|s;
int t=ok(ste,i);
int sum=dfs(s,k-t);
if(k-sum>maxx)
maxx=k-sum;
}
}
return dp[ste]=maxx;
}
int main()
{
int T,tt=0;
scanf("%d",&T);
init();
while(T--)
{
memset(vis,0,sizeof(vis));
scanf("%d",&n);
tom=0,jerry=0;
int s=0,ste=0;
for(int i=0;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
if(x>y)swap(x,y);
vis[mp[x][y]]=1;
int s1=judge();
if(i&1)
{
jerry+=(s1-s);
}
else
{
tom+=(s1-s);
}
s=s1;
/// printf("(%d %d)\n",tom,jerry);
}
cnt=-1;
for(int i=1;i<=24;i++)
{
if(!vis[i]) x[++cnt]=i;
}
s=9-judge();
memset(dp,-1,sizeof(dp));
int num=dfs(0,s);
printf("Case #%d: ",++tt);
if((n&1)==0)
{
if(tom+num>jerry+s-num)
printf("Tom200\n");
else
printf("Jerry404\n");
}
else
{
if(tom+s-num>jerry+num)
printf("Tom200\n");
else
printf("Jerry404\n");
}
}
return 0;
}
标签:
原文地址:http://blog.csdn.net/lvshubao1314/article/details/45225759