文思海辉第一届在线编程大赛--开源探究
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剪枝
高级一点的状态空间缓存,最小窗口移动等。
先贴一个写最大最小搜索的代码吧。
后记:
这个题限制了最长字符不超过15,如果知道最大最小搜索就知道字符长度对计算时间的影响非常大。
这个代码计算结果应该没问题,但是字符长时间开销没有优化。提交的时候应为超时失败了。
如果纯用标准算法,要想15步在3秒内算完还是比较困难的,所以针对题目做特例化优化是一个方向。
欢迎大家在基础上优化提高。
甲乙两个人用一个英语单词玩游戏。两个人轮流进行,每个人每次从中删掉任意一个字母,如果剩余的字母序列是严格单调递增的(按字典序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秒内算完还是比较困难的,所以针对题目做特例化优化是一个方向。
欢迎大家在基础上优化提高。
相关文章推荐
- 文思海辉第一届在线编程大赛:单词博弈 -dp+博弈
- 英雄会第一届在线编程大赛:单词博弈 (解题思路) ---miss若尘
- 庞果网英雄会第一届在线编程大赛:单词博弈
- 第一届文思在线编程大赛题解析。
- 参与英雄会第一届在线编程大赛:单词博弈
- 英雄会第一届在线编程大赛:单词博弈
- 英雄会第一届在线编程大赛解题思路
- 英雄会第一届在线编程大赛:单词博弈 (C++代码) ---miss若尘
- 庞果网英雄会第一届在线编程大赛:单词博弈
- NYOJ--1126--csdn第五届在线编程大赛-完全平方
- 第五届在线编程大赛月赛第一题:完全平方数的个数
- csdn 英雄会第四届在线编程大赛·线上初赛:带通配符的数
- 微软必应-英雄会第三届在线编程大赛:几个Bing?【英雄会】
- 用python实现csdn第四届在线编程大赛·线上初赛:带通配符的数
- CSDN英雄会-第五届在线编程大赛月赛第三题:石子游戏(1)
- 英雄会第二届在线编程大赛·线上初赛:AB数
- 单词博弈解题思路 文思海辉编程大赛
- CSDN英雄会——第五届在线编程大赛月赛指定题目:反向互补子串
- 文思海辉编程大赛的初体验
- 【题解】 英雄会-第五届在线编程大赛月赛第二题:走格子