您的位置:首页 > 编程语言

单词博弈解题思路 文思海辉编程大赛

2013-12-30 20:50 274 查看
博客,这里开始了我人生的又一个有意义的第一次——第一次写个人博客。

。。。好吧,主要还是学习如何写博客,记录自己成长的过程,在这里就记下这题“单词博弈”解题思路,写写个人思路,也非常欢迎江湖有志同道合的朋友共同探讨!

/******************************************************************华丽的分割线********************************************************************************/

题目详情

甲乙两个人用一个英语单词玩游戏。两个人轮流进行,每个人每次从中删掉任意一个字母,如果剩余的字母序列是严格单调递增的(按字典序a < b < c <....<z),则这个人胜利。两个人都足够聪明(即如果有赢的方案,都不会选输的方案 ),甲先开始,问他能赢么?

输入: 一连串英文小写字母,长度不超过15,保证最开始的状态不是一个严格单增的序列。

输出:1表示甲可以赢,0表示甲不能赢。

例如: 输入 bad, 则甲可以删掉b或者a,剩余的是ad或者bd,他就赢了,输出1。

又如: 输入 aaa, 则甲只能删掉1个a,乙删掉一个a,剩余1个a,乙获胜,输出0。

题目不难理解,就是一场博弈,看谁先得到必胜态,思路就是去分析当前状态得到SG函数,如果下一次操作得到的状态全部是必败状态,那么推出当前状态即为必胜状态;否则,如果下次操作得到的状态中有必胜状态,那么当前状态则定义为必败状态,因为操作者可以通过当前状态到达必胜状态。

由此,我们可以通过DFS搜索,从当前状态出发,预测能得到的状态有哪些,并尝试记录已经求出的状态,避免重复搜索,实现记忆化搜索。这里,我们注意到字母序列的长度最大为15,因此我们一共会得到2^15种状态,这样做的效果很不错,希望你会喜欢!


#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
int map[33010];
int wlen;

bool checkUp(int stat,string word)
{
char ch=123;
for (int i=0;i<wlen;++i)
{
if ((1<<i)&stat)
{
if (word.at(wlen-i-1)>=ch)
{
return false;
}
else
{
ch=word.at(wlen-i-1);
}
}
}
return true;
}

int DFS(int stat,string word)
{
if (map[stat]>-1)
{
return map[stat];
}
if (checkUp(stat,word))
{
return map[stat]=0;
}
int res=1;
for (int i=0;(1<<i)<=stat;++i)
{
if ((1<<i)&stat)
{
res&=DFS((1<<i)^stat,word);
}
}
return map[stat]=res^1;
}

class Test {
public:
static int who (string   word)
{
wlen=word.length();
int stat=(1<<wlen)-1;
for (int i=0;i<=stat;++i)
{
map[i]=-1;
}
return DFS(stat,word);
return 0;
}
};
//start 提示:自动阅卷起始唯一标识,请勿删除或增加。
int main()
{
cout<<Test::who("Test")<<endl;
}
//end //提示:自动阅卷结束唯一标识,请勿删除或增加。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息