2023-04-07 00:49阅读: 260评论: 0推荐: 0

蓝桥-13届-C++-A组-省赛-B题-灭鼠先锋

题意在于对于所有可能的四种情况,是否先手必胜

完全没思路,直接看答案:

1、首先确定结束状态:只剩下 1 个棋子时为必败态

2、博弈状态转移基本策略:

  • 可以转移到必败态的状态,为必胜态
  • 只能转移到必胜态的状态,为必败态

怎么理解这两句话?

首先是对 必胜态/必败态的定义

必胜态:对于当前的博弈局面,当前玩家可以通过正确的策略,保证必定取得胜利
必败态:当前玩家无论如何都会失败

注意:在不考虑平局态的情况下,必胜态+必败态=所有的可能
可能胜也可能败的状态属于必胜态
这是因为对于某个玩家来说,只要存在一种策略可以使得这个玩家赢得比赛,那么这个状态就是必胜态

// 判断是否仅存在一个空格(O)
// 扫描字符串并对O的数量计数
bool check(string s) {
int tot = 0;
for (auto x : s)
if (x == 'O') tot++;
return tot == 1;
}
map<string, bool> sg;
/*
* 后手必胜/必败
*/
bool dfs(string str) {
if (sg.count(str)) return sg[str];// 记忆化
// 如果只有一个空位,也就是说后手必败
if (check(str)) return sg[str] = false;// 先赋值后返回,可读性差
/*
* 模拟放一个的情况
*/
for (int i = 0; i < str.size(); i++) {
if (str[i] == 'O') {
string temp = str;
temp[i] = 'X';
// 可达必败均为必胜
// 意思是存在当前选手下了某一步棋之后,后面的选手不管怎么下都必败
if (!dfs(temp)) return sg[str] = true;
}
}
/*
* 模拟放两个的情况
*/
for (int i = 0; i < str.size() - 1; i++) {
// i!=3是什么意思?因为这里是把两行排成一行了,不能第一行最后一个+第二行第一个算作连续两个
if (str[i] == 'O' && str[i + 1] == 'O' && i != 3) {
string temp = str;
temp[i] = temp[i + 1] = 'X';
// 可达必败均为必胜
if (!dfs(temp)) return sg[str] = true;
}
}
// 只达必胜均为必败
// 排除了所有可能到达必败态的情况,接下来不管自己或者下一步对方怎么下对方都必胜,自己必败
return sg[str] = false;
}
int main() {
// 表示棋盘的四种状态
string s[] = { "XOOOOOOO", "XXOOOOOO", "OXOOOOOO", "OXXOOOOO" };
for (string str : s) {
if (dfs(str))cout << 'L';// 后手必胜
else cout << 'V';
}
return 0;
}

代码中模拟了所有的可能放置情况,并对其做了记忆以提高效率

本文作者:YaosGHC

本文链接:https://www.cnblogs.com/yaocy/p/17196355.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   YaosGHC  阅读(260)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起