您的位置:首页 > 其它

ZOJ1827_The Game of 31

2013-10-17 21:41 295 查看
这是一个比较经典的博弈题目,今年网赛好像是南京赛上有一个类似的题目。

这种题目是没有一定公式或者函数的,需要自己dp或者搜索解决。

题意为分别给你4张写有1,2,3,4,5,6的卡片共24张,每次轮流拿一张卡片,且所有被拿过的卡片的总和不能超过31,谁无法拿出卡片就fail。

首先对于每种卡片一共可能有5中存在情况,所以六张卡片一共有5^6种情况,同时我们保存当前拿到的卡片的数量的和,然后记忆化搜就行了。

记得每次取最优,同时还要注意除掉拿过的牌,当前是谁第一个拿牌哦。

#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 20000
using namespace std;

int dig[7],f[35][maxn];//f[i][j]表示和为i,状态为j的时候是否是必胜状态,如果是的话,值为1,否则值为-1.0表示没有搜过。j用的是5进制,这里比较巧妙。
char s[50];

int dfs(int tot,int cur)
{
if (f[tot][cur]!=0) return f[tot][cur];
for (int i=1; i<=6; i++)
{
if (tot+i>31) continue;
if ((cur/dig[i])%5==0) continue;
if (dfs(tot+i,cur-dig[i])==-1)
{
return f[tot][cur]=1;
}
}
return f[tot][cur]=-1;
}

int main()
{
int ans,cur,tot,tep;
dig[1]=1;
dig[0]=4;
for (int i=2; i<=6; i++) dig[i]=5*dig[i-1],dig[0]+=4*dig[i];//五进制预处理。
while (gets(s))
{
memset(f,0,sizeof f);
cur=dig[0],tot=0;
for (int i=0; s[i]; i++)
{
tep=s[i]-'0';
tot+=tep;
cur-=dig[tep];
}
if (strlen(s)&1) ans=-1; else ans=1;
ans*=dfs(tot,cur);
if (ans==-1) printf("%s B\n",s);
else printf("%s A\n",s);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: