蓝桥杯-填字母游戏(无偏博弈类问题)
问题描述:
K大师在纸上画了一行n个格子,要小明和他交替往其中填入字母。 1. 轮到某人填的时候,只能在某个空格中填入L或O 2. 谁先让字母组成了“LOL”的字样,谁获胜。 3. 如果所有格子都填满了,仍无法组成LOL,则平局。 小明试验了几次都输了,他很惭愧,希望你能用计算机帮他解开这个谜。 本题的输入格式为: 第一行,数字n(n<10),表示下面有n个初始局面。 接下来,n行,每行一个串,表示开始的局面。 比如:“******”, 表示有6个空格。“L****”, 表示左边是一个字母L,它的右边是4个空格。 要求输出n个数字,表示对每个局面,如果小明先填,当K大师总是用最强着法的时候,小明的最好结果。 1 表示能赢 -1 表示必输 0 表示可以逼平
输入
4 *** L**L L**L***L L*****L
输出
0 -1 1 1
问题分析:
首先,对于此问题,我们要明白,它是有偏博弈,还是无偏博弈。
无偏博弈:在组合博弈论里,无偏博弈是一类任意局势对于游戏双方都是平等的回合制双人游戏。这里平等的意思是所有可行的走法仅仅依赖于当前的局势,而与现在正要行动的是哪一方无关。换句话说,两个游戏者除了先后手之外毫无区别。
有偏博弈:除无偏博弈外,其余博弈皆为有偏博弈
当填入一个字母时,我们要考虑两个问题,一是是否形成了LOL这个字符串,二是是否还存在空格,如果是第一种情况,则说明对方输了,我方赢了,如果不存在空格了,说明将有可能平局,因此,问题就简化为对每一个要填的空,做上述的判断,形成了一个递归。
代码描述:
/*LOL填字游戏 我方先填 */ #include<iostream> #include<cstdlib> #include<string> using namespace std; int is_lol(string x); int main(){ string x; cout<<is_lol("***")<<endl; cout<<is_lol("L**L")<<endl; cout<<is_lol("L**L***L")<<endl; cout<<is_lol("L*****L")<<endl; return 0; } int is_lol(string x){ /*1表示能赢 0表示平局 -1表示输 */ int len=x.length(); if(x.find("LOL")!=string::npos) return -1;//当我方开始填时已出现LOL时,则我方输 if(x.find("*")==string::npos) return 0;//当没有出现LOL时,且没有空格则为平局 int ping=0;//先假设为平局 for(int i=0;i<len;i++){ if(x[i]=='*'){ x[i]='L'; switch(is_lol(x)) { case -1: return 1;//当我方填完后,出现LOL,则我方赢 case 0: ping=1;//当我方填完后,没有空格,则为平局 } x[i]='O'; switch(is_lol(x)) { case -1: return 1;//当我方填完后,出现LOL,则我方赢 case 0: ping=1;//当我方填完后,没有空格,则为平局 } x[i]='*'; } } if(ping) return 0;//如果存在平局,则结果为平局,否则即输 return -1; }