蓝桥杯 填字母游戏

填字母游戏

原题目链接

问题背景

小明沉迷 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];
相关推荐
huwuhang30 分钟前
索尼PS3游戏合集【中文游戏】8.12T 1430个游戏+PS3模拟器
android·游戏·智能手机·游戏机·电视
毕业设计-小慧31 分钟前
计算机毕业设计springboot游戏数据管理系统 基于SpringBoot的电竞赛事数据管理平台 基于SpringBoot的在线游戏运营数据分析系统
spring boot·游戏·课程设计
Alicx.1 小时前
dfs由易到难
算法·蓝桥杯·宽度优先
心软小念2 小时前
金三银四,全网最详细的软件测试面试题总结
软件测试·面试·职场和发展
黑客说3 小时前
AI驱动剧情,解锁无限可能——AI游戏发展解析
人工智能·游戏
软件测试媛4 小时前
软件测试常见的面试题(46道)
功能测试·面试·职场和发展
IronMurphy4 小时前
【算法三十一】46. 全排列
算法·leetcode·职场和发展
智算菩萨4 小时前
【OpenGL】10 完整游戏开发实战:基于OpenGL的2D/3D游戏框架、物理引擎集成与AI辅助编程指南
人工智能·python·游戏·3d·矩阵·pygame·opengl
红云梦6 小时前
简历投了 100 份没回音?我给面试平台加了个“简历雷达“
人工智能·面试·职场和发展
风酥糖7 小时前
Godot游戏练习01-第20节-增加亿点点细节
游戏·游戏引擎·godot