蓝桥杯 填字母游戏

填字母游戏

原题目链接

问题背景

小明沉迷 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];
相关推荐
xiezhr2 天前
米哈游36岁程序员被曝复工当晚猝死出租屋内
游戏·程序员·游戏开发
qq_459234425 天前
【题库】| 商用密码应用安全性评估从业人员考核题库(四十)
职场和发展·密码学·学习方法·考核·商用密码·商用密码应用安全性评估·密评
爱搞虚幻的阿恺5 天前
Niagara粒子系统-超炫酷的闪电特效(加餐 纸牌螺旋上升效果)
游戏·游戏引擎
敲敲了个代码5 天前
[特殊字符] 空数组的迷惑行为:为什么 every 为真,some 为假?
前端·javascript·react.js·面试·职场和发展
智算菩萨6 天前
儿童游乐空间的双维建构:室内淘气堡与室外亲子乐园的发展学理、功能分野与协同育人机制研究
游戏·游戏策划
marteker6 天前
房地产市场平台Zillow与《魔兽世界》合作展示游戏内房屋
游戏
诚思报告YH6 天前
视频面试软件市场洞察:2026 - 2032年复合年均增长率(CAGR)为10.3%
面试·职场和发展
重生之后端学习6 天前
74. 搜索二维矩阵
开发语言·数据结构·算法·职场和发展·深度优先
tyb3333336 天前
leetcode:吃苹果和队列
算法·leetcode·职场和发展
Pitiless-invader6 天前
MySQL 相关知识及面试问题汇总
面试·职场和发展