庞果网英雄会第一届在线编程大赛:单词博弈
题目如下
甲乙两个人用一个英语单词玩游戏。两个人轮流进行,每个人每次从中删掉任意一个字母,如果剩余的字母序列是严格单调递增的(按字典序a < b < c <....<z),则这个人胜利。两个人都足够聪明(即如果有赢的方案,都不会选输的方案 ),甲先开始,问他能赢么?
输入: 一连串英文小写字母,长度不超过15,保证最开始的状态不是一个严格单增的序列。
输出:1表示甲可以赢,0表示甲不能赢。
例如: 输入 bad, 则甲可以删掉b或者a,剩余的是ad或者bd,他就赢了,输出1。
又如: 输入 aaa, 则甲只能删掉1个a,乙删掉一个a,剩余1个a,乙获胜,输出0。
分析:由于假设了两人足够聪明,即轮到某个人删除字母的时候,他一定会选对自己最有利的选择。例如轮到甲删除的时,甲想赢得游戏,那么一定存在一种选择使得甲删除该字母后,无论乙怎么选择都会导致甲赢,否则甲就会输。
这一题可以采用dfs+记录表的方法,利用两个记录表(map)分别记录甲乙两人已经操作过的单词子串以防止计算重复子问题(例如对于单词abcd,下面两种情况下对单词子串cd有重复计算,甲删除a,乙再删除b,然后甲要对单词cd进行删除;甲删除b,乙删除a,甲对单词cd进行删除)。
记录表amap[s] = true 表示字符串s由甲来删除时,甲会赢得游戏,= false则表示甲会输
记录表bmap[s] = true 表示字符串s由乙来删除时,甲会赢得游戏,= false则表示甲会输(注意是甲是否会赢得游戏)
class Test {
public:
typedef map<string, bool> Map;
static int who (string word)
{
//用map保存子问题,防止重复计算
//amap[s]表示字符串s由甲操作时甲能否获胜
//bmap[s]表示字符串s由乙操作时甲能否获胜
Map amap, bmap;
return (int)dfs(word, 1, amap, bmap);
}
private:
//判断字符串是否严格递增
static bool isIncrease(string &s)
{
int len = s.size();
for(int i = 1; i < len; i++)
if(s[i] <= s[i-1])return false;
return true;
}
//id == 1表示接下来由甲操作,否则是乙
//返回true表示甲会赢得游戏,返回false则甲会输
static bool dfs(string &s, bool id, Map &amap, Map &bmap)
{
if(isIncrease(s))
{
if(id == 0)
return true;
else return false;
}
int len = s.size();
for(int i = 0; i < len; i++)
{
string subs = s;
subs.erase(i,1);
bool tmp;
if(id == 0)
{//由乙操作时,要所有情况返回true,即所有情况乙都会输,甲就赢得游戏
if(bmap.find(subs) == bmap.end())
{
tmp = dfs(subs, id^true, amap, bmap);
bmap[subs] = tmp;
}
else tmp = bmap[subs];
if(tmp == false)return false;
}
else
{//由甲操作时,只要一种情况返回true,甲就赢得游戏
if(amap.find(subs) == amap.end())
{
tmp = dfs(subs, id^true, amap, bmap);
amap[subs] = tmp;
}
else tmp = amap[subs];
if(tmp == true)return true;
}
}
if(id == 0)
return true;
else return false;
}
};
调用Test::who(sting word) 来判断对于单词word甲是否会赢
【版权声明】转载请注明出处:http://www.cnblogs.com/TenosDoIt/p/3485090.html

浙公网安备 33010602011771号