蓝桥杯 历届试题 填字母游戏(记忆化搜索)

    科技2022-08-04  128

    问题描述

    小明经常玩 LOL 游戏上瘾,一次他想挑战K大师,不料K大师说: “我们先来玩个空格填字母的游戏,要是你不能赢我,就再别玩LOL了”。 K大师在纸上画了一行n个格子,要小明和他交替往其中填入字母。 并且: 1. 1. 1.轮到某人填的时候,只能在某个空格中填入L或O 2. 2. 2.谁先让字母组成了“LOL”的字样,谁获胜。 3. 3. 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

    //算法大体框架(QueryAns存储搜索过的str) int dfs(str){ if(IsQuery(str)) return QueryAns(str); //记忆化搜索 if(当前操作能赢) return QueryAns(str)=1; if(当前当前操作能平手) return QueryAns(str)=1; return QueryAns(str)=-1; //无法胜出或达成平手,必输 } #include<bits/stdc++.h> using namespace std; const int N=1e5+5; map<string,int>dp; char str[N]; int dfs(char *str,int n){ if(dp.find(str)!=dp.end()) return dp[str]; if(strstr(str,"LO*")||strstr(str,"L*L")||strstr(str,"*OL")) return dp[str]=1; if(!strstr(str,"*")) return dp[str]=0; int flag=-1; for(int i=0;i<n;++i){ if(str[i]=='*'){ str[i]='O'; int ret=dfs(str,n); if(ret==-1){ str[i]='*'; return dp[str]=1; } if(ret==0) flag=0; str[i]='L'; ret=dfs(str,n); if(ret==-1){ str[i]='*'; return dp[str]=1; } if(ret==0) flag=0; str[i]='*'; } } return dp[str]=flag; } int main(){ int t;scanf("%d",&t); while(t--){ scanf("%s",str); printf("%d\n",dfs(str,strlen(str))); } return 0; }
    Processed: 0.023, SQL: 8