注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

fudq's AC Road

何以解忧,唯有AC!

 
 
 

日志

 
 

hdu 4753 Fishhead’s Little Game  

2013-09-21 22:22:07|  分类: ACM-hdu |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
http://acm.hdu.edu.cn/showproblem.php?pid=4753
题意:2013南京网络赛。两人轮流给九宫格加边,如果加的边能组成一个边长为1的正方形,则得分加1,如果能组成两个,则加2分。现在两人轮流进行了n局,问两人继续用最优策略玩下去,最后谁赢,Tom得分高就Tom赢,否则Jerry赢。
题解:
这题做得很纠结,刚开始以为就是个纯模拟,后来发现题意理解不对,是个博弈。分析下,发现数据不太,九宫格就24条边,而且给出的边最少有12条,于是想到了解NP问题的博弈搜索,按所有可行边搜索。如果是叶子节点则看最后的得分,得分高的为赢;否则看该节点的所有子节点,如果有一个子节点为输则当前节点为赢,如果子节点都为赢,则当前节点为输。
算法是金牛想的,代码我打的,由于之前没打过类似的搜索树,打完发现出的几组数据都不对,wa了好几发,等调完所有bug又发现T了,当时比赛还有两分钟结束,金牛加了剪枝wa,比赛结束还是没过。。。
比赛结束后,和队友一起调代码,当找到子节点为输的状态返回时,没有清理状态,加上一句代码后就A了。。。。
哎,练得还是太少,弱爆了。。。
比赛后看了下大家的做法,差不多都是记忆化搜索,比赛时也想到过,没想清楚状态就pass了。。。

/*
* pro.cpp
*
* Created on: 2013-09-21
* Author: fudq
*/
#include <functional>
#include <algorithm>
#include <iostream>
//#include <fstream>
#include <sstream>
#include <iomanip>
#include <numeric>
#include <cstring>
#include <cassert>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,102400000")

#define FOR(i,a) for((i)=0;i<(a);(i)++)
#define MEM(a) (memset((a),0,sizeof(a)))
#define LL __int64

const int N=1010;
const int M=32010;
const int MOD=1000000007ll;
const int INF=0x7fffffff;
const int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
//const int dir[8][2]={{-1,0},{1,0},{0,-1},{0,1},{-1,1},{1,-1},{-1,-1},{1,1}};
const double eps=1e-7;
const double PI=acos(-1.0);

inline int sign(double x){return (x>eps)-(x<-eps);}
template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
template<class T> inline T lcm(T a,T b,T d){return a/d*b;}
template<class T> inline T Min(T a,T b){return a<b?a:b;}
template<class T> inline T Max(T a,T b){return a>b?a:b;}
template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}
template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}
template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));}
template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));}
/*************************/

int n,f[22][22];

int jud(int a,int b)
{
int tmp=0;
if(a>b)
swap(a,b);
if(b-a == 1)
{
if(a >= 5 && f[a][b]==1 && f[a][a-4]==1 && f[b][b-4]==1 && f[a-4][b-4]==1)
tmp++;
if(b <= 12 && f[a][b]==1 && f[a][a+4]==1 && f[b][b+4]==1 && f[a+4][b+4]==1)
tmp++;
}
else
{
if((a-1)%4!=0 && f[a][a-1]==1 && f[b][b-1]==1 && f[a][b]==1 && f[a-1][b-1]==1)
tmp++;
if(a%4!=0 && f[a][a+1]==1 && f[b][b+1]==1 && f[a][b]==1 && f[a+1][b+1]==1)
tmp++;
}
return tmp;
}

//如果是叶子节点则看得分,得分高的为赢;否则看节点的所有子节点,如果有一个节点为输则当前节点为赢,如果子节点都为赢,则当前节点为输
bool dfs(int s1,int s2,bool tom)
{
bool res=false,flag=false;
for(int i=1;i<=16;i++)
{
if(i%4!=0 && !f[i][i+1] && !f[i+1][i]) //横边
{
flag=true;
f[i][i+1]=f[i+1][i]=true;
int tmp = jud(i,i+1);
if (!dfs(s2,s1+tmp,!tom)) //剪枝,如果子节点有输的状态则返回;到下一层时,博弈交换顺序,所以dfs要换下得分
{
f[i][i+1]=f[i+1][i]=false; //return前别忘记清状态
return true;
}
f[i][i+1]=f[i+1][i]=false;
}
if(i<=12 && !f[i][i+4] && !f[i+4][i]) //竖边
{
flag=true;
f[i][i+4]=f[i+4][i]=true;
int tmp = jud(i,i+4);
if (!dfs(s2,s1+tmp,!tom))
{
f[i][i+4]=f[i+4][i]=false;
return true;
}
f[i][i+4]=f[i+4][i]=false;
}
}
if(!flag) //如果是叶子节点看得分
{
if (s1 == s2)
return !tom;
return s1 > s2;
}
return res;
}

void solve()
{
int i,a,b,s1=0,s2=0;
bool tom_turn = true;
MEM(f);
for(i=0;i<n;i++) //先模拟计算之前的得分
{
scanf("%d%d",&a,&b);
f[a][b]=f[b][a]=true;
int tmp = jud(a,b);
if(tom_turn)
s1+=tmp;
else
s2+=tmp;
tom_turn = !tom_turn;
}
// printf("%d %d\n",s1,s2);

bool tom, jerry;
if(tom_turn)
{
tom=dfs(s1,s2,true);
jerry = !tom;
}
else
{
jerry=dfs(s2,s1,false);
tom = !jerry;
}
if(tom)
printf("Tom200\n");
else
printf("Jerry404\n");
}

int main()
{
#ifndef ONLINE_JUDGE
freopen("testin.txt", "r", stdin);
//freopen("textout.txt", "w", stdout);
#endif
int T,cas=1;
scanf("%d",&T);
while(T--)
{
printf("Case #%d: ",cas++);
scanf("%d",&n);
solve();
}
return 0;
}




  评论这张
 
阅读(432)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017