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

文思海辉第一届在线编程大赛--开源探究

2013-11-27 17:41 351 查看
题目详情

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

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

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

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

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

题目分析:其实一看题就知道是一个博弈的算法题。

最基本的最大最小搜索,alpha-beta剪枝

高级一点的状态空间缓存,最小窗口移动等。

先贴一个写最大最小搜索的代码吧。

#include<iostream>
#include<string>
using namespace std;
#define         MAX_NUM         15

struct State//该结构表示状态,也可看做搜索树中的一个节点
{
char QP[MAX_NUM];
bool IsDel[MAX_NUM];
bool win[MAX_NUM];
}; //用来保存搜索树中状态节点的数组

class Test {
public:
static int who (string word)
{
Init(word);
int s = AutoDone(StateInit, 0);
return s;
};

private:
static void Init(const string &a)   //初始化函数
{
for(int i = 0; i < MAX_NUM; i++)
{
StateInit.IsDel[i] = true;
}

for(int i = 0; i < a.size() && i < MAX_NUM; i++) {
StateInit.QP[i] = a[i];
StateInit.IsDel[i] = false;
}
};

static void PrintQP(const struct State &s, int l, bool rt, bool iswin)  //打印状态
{
return;
cout<< l << "\t" << "now is:";
for(int i=0; i<MAX_NUM; i++)
{
if (!s.IsDel[i])
cout<< s.QP[i] <<" ";
}
if (rt)
{
if (iswin)
cout<<" Win" << endl;
else
cout<<" Lose" << endl;
}
};

static bool IsWin(State s) //判断是否赢了
{
char last = '0';
for (int i = 0; i < MAX_NUM; i++) {
if (last == '0') {
if (!s.IsDel[i]) {
last = s.QP[i];
}
} else {
if (!s.IsDel[i]) {
if (s.QP[i] <= last)
return false;
else
last = s.QP[i];
}
}
}
return true;
};

//计算机通过该函数决定走哪一步
static bool AutoDone(const struct State &state, int l)
{
bool max_min = (l % 2);
if(IsWin(state))//如果赢了
{
return max_min;
}

State status[MAX_NUM];
for (int i = 0; i < MAX_NUM; i++)
{
memcpy(&status[i], &state, sizeof(State));
if(status[i].IsDel[i]) continue;
//假设删除一个
status[i].IsDel[i] = true;
status[i].win[i] = AutoDone(status[i], l+1);
if (!max_min) {
if (status[i].win[i]) return true;
} else {
if (!status[i].win[i]) return false;
}
//status[i].IsDel[i] = false;
}

if (!max_min) {
for (int i = 0; i < MAX_NUM; i++)
{
if(status[i].IsDel[i]) continue;
if (status[i].win[i]) {
return true;
}
}

return false;
} else {
for (int i = 0; i < MAX_NUM; i++)
{
if(status[i].IsDel[i]) continue;
if (!status[i].win[i]) {
return false;
}
}
return true;
}
};

static struct State StateInit;
};

State Test::StateInit;

//主程序
int main()
{
cout<<Test::who("bad")<<endl;
return 0;
}


后记:
这个题限制了最长字符不超过15,如果知道最大最小搜索就知道字符长度对计算时间的影响非常大。

这个代码计算结果应该没问题,但是字符长时间开销没有优化。提交的时候应为超时失败了。

如果纯用标准算法,要想15步在3秒内算完还是比较困难的,所以针对题目做特例化优化是一个方向。

欢迎大家在基础上优化提高。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: