蓝桥杯 填字母游戏

填字母游戏

原题目链接

问题背景

小明沉迷 LOL。K 大师与他先玩一个"在空格中填字母"的小游戏:

两人轮流在一行格子中,把某个空格替换为 LO。谁先在整行字符串中形成子串 "LOL" ,谁就获胜 ;若所有格子填满仍无法形成 "LOL",则平局

游戏规则

  • 初始给定一行由 LO*(表示空格)组成的字符串。
  • 两名玩家轮流行动,每回合:
    • 选择任意一个 *,将其替换为 LO
  • 判定:
    • 任何时刻,一旦行内出现连续的 "LOL",当前行动的玩家立刻获胜
    • 若所有 * 均被替换完仍未出现 "LOL",则平局

目标

对每个给定的初始局面,假设小明先手 且双方都采用最优策略,输出小明能达到的最好结果

  • 1:先手必胜;
  • 0:先手可保平;
  • -1:先手必败。

输入格式

  • 第 1 行:整数 nn < 10),表示有 n 个初始局面。
  • 接下来的 n 行:每行一个只包含 LO* 的字符串,表示一个初始局面(例如:
    • "******":6 个空格;
    • "L****":左端一个 L,其后 4 个空格)。

输出格式

  • 输出 n 行,每行一个整数,分别对应每个初始局面的最好结果:
    • 10-1(含义见上文"目标")。

示例

输入

in 复制代码
4
***
L**L
L**L***L
L*****L

输出

out 复制代码
0
-1
1
1

c++代码

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

int n;
string s;
unordered_map<string, int> mp;

int result() {
    if (mp.find(s) != mp.end()) return mp[s];
	if (s.find("LOL") != -1) {mp[s] = -1; return -1;}
	if (s.find("*") == -1) {mp[s] = 0; return 0;}
	int key = -1;
	for (int i = 0; i < s.size(); i++) {
		if (s[i] != '*') continue;
		s[i] = 'L';
		int sym = result();
		if (sym == -1) {
			s[i] = '*';
			mp[s] = 1;
			return 1;
		}
		else if (sym == 0) key = 0;
		s[i] = 'O';
		sym = result();
		if (sym == -1) {
			s[i] = '*';
			mp[s] = 1;
			return 1;
		}
		else if (sym == 0) key = 0;
		s[i] = '*';
	}
	mp[s] = key;
	return key;
}

int main() {
	cin >> n;
	while (n--) {
		cin >> s;
		cout << result() << endl;
	}
	return 0;
}

题目解析

博弈论(递归+回溯)

如果敌方必赢,那么我方必输,如果敌方必输那么我方必赢。否则可以平局。

c++ 复制代码
if (sym == -1) {
    return 1;
}

int sym()的返回值表示,当前局面,先下棋的人的输赢。

我们枚举先下棋的人这一步的每一种下法。

cpp 复制代码
for (int i = 0; i < s.size(); i++) {
    if (s[i] != '*') continue;
    s[i] = 'L';
    //...省略代码
    s[i] = '*';.//回溯
    //...省略代码
    s[i] = 'O';
    s[i] = '*';//回溯
}

然后下一步就轮到敌方下。我们再次调用sym函数获得敌方输赢。

cpp 复制代码
s[i] = 'L';
int sym = result();
if (sym == -1) {
    //...
    return 1;
}

一直枚举每一种下法,直到已经分出胜负才停止。

如果敌方的每一种返回值都是必赢那么我们必输。

如果敌方只要有一个必输那么我们必赢。

否则可以平局。

记忆化搜索

递归过程中会出现很多重复情况,而每一种情况的返回值都是一样的。

为了不重复走我们已经模拟过的情况,我们用unorder_map把我们走过的每一种情况存储下来。

下次我们遇到重复的情况的时候,直接返回存储的值,而不是再次递归搜索。

cpp 复制代码
if (mp.find(s) != mp.end()) return mp[s];
相关推荐
逆境清醒10 小时前
2020年多媒体应用设计师考试上午真题答案解释(2)
职场和发展·多媒体应用设计师·水平考试
m0_7369270411 小时前
Java面试场景题及答案总结(2025版持续更新)
java·开发语言·后端·职场和发展
007php00720 小时前
某游戏大厂 Java 面试题深度解析(四)
java·开发语言·python·面试·职场和发展·golang·php
程序员三藏1 天前
Postman持久化保存/设置断言详解
自动化测试·软件测试·python·测试工具·职场和发展·接口测试·postman
夏鹏今天学习了吗1 天前
【LeetCode热题100(56/100)】组合总和
算法·leetcode·职场和发展
测试19981 天前
如何写出一个完整的测试用例?
自动化测试·软件测试·python·测试工具·职场和发展·测试用例·接口测试
.ZGR.1 天前
蓝桥杯高校新生编程赛第二场题解——Java
java·算法·蓝桥杯
IDOlaoluo1 天前
vc_redist.x64.exe安装方法,解决软件游戏缺少运行库问题
游戏
AA陈超1 天前
虚幻引擎5 GAS开发俯视角RPG游戏 P06-28 构建属性菜单小部件控制器
c++·游戏·ue5·游戏引擎·虚幻
da_vinci_x1 天前
Substance Designer“程序化地形”与“Splat Map”生成管线
游戏·aigc·设计师·贴图·技术美术·游戏美术·substance designer