标题:填字母游戏小明经常玩 LOL 游戏上瘾,一次他想挑战K大师,不料K大师说:“我们先来玩个空格填字母的游戏,要是你不能赢我,就再别玩LOL了”。K大师在纸上画了一行n个格子,要小明和他交替往其中填入字母。并且:1. 轮到某人填的时候,只能在某个空格中填入L或O2. 谁先让字母组成了“LOL”的字样,谁获胜。3. 如果所有格子都填满了,仍无法组成LOL,则平局。小明试验了几次都输了,他很惭愧,希望你能用计算机帮他解开这个谜。本题的输入格式为:第一行,数字n(n<10),表示下面有n个初始局面。接下来,n行,每行一个串,表示开始的局面。比如:“******”, 表示有6个空格。“L****”, 表示左边是一个字母L,它的右边是4个空格。要求输出n个数字,表示对每个局面,如果小明先填,当K大师总是用最强着法的时候,小明的最好结果。1 表示能赢-1 表示必输0 表示可以逼平例如,输入:4***L**LL**L***LL*****L则程序应该输出:0-111
代码中每一步都做了详细的注释,所以不过多的解释了。做了两道回溯的题,感觉呢好像很套路的样子。无非就是,先试探一下,如果我这样做了,对手面对剩下的局面是否能赢,再用if判断一下,结果就很容易看出来了。之前一听到博弈,就觉得好高深的样子。现在貌似有了一知半解,觉得很有趣。神奇的计算机啊~
package dibajie;import java.util.Scanner;/** 采用的方法:博弈+递归+回溯* 1. 轮到某人填的时候,只能在某个空格中填入L或O2. 谁先让字母组成了“LOL”的字样,谁获胜。3. 如果所有格子都填满了,仍无法组成LOL,则平局。1 表示能赢-1 表示必输0 表示可以逼平*/public class LOL {private static int fun(char[] arr) {// 判断出口// 如果当我拿到字符串的时候,对手已经写好了“LOL” 我必输无疑// 当我拿到字符串,已经没有空格了,那就是平局// 在不平局,也不能是必输无疑的时候,找方法看看我能不能赢String s = new String(arr);if (s.contains("LOL")) {return -1;}if (s.contains("*") == false) {return 0;}boolean flag_pingju = false;for (int i = 0; i < arr.length; i++) {if (arr[i] == '*') {try {//先把L写进去,试探一下。如果对手必输,那我们就赢arr[i] = 'L';if (fun(arr) == -1)return 1;if (fun(arr) == 0){flag_pingju = true;}//再把O写进去,试探一下,同上 arr[i] = 'O';if (fun(arr) == -1)return 1;if (fun(arr) == 0){flag_pingju = true;}} finally {// 使用try——finally包围起来的好处是:无论在try模块是否有return 都会执行finally里面的句子//回溯arr[i] = '*';}}}if (flag_pingju == true) {// 如果对方可以吧局面逼平,那么我来尝试是否可以莹return 0;} else {return -1;}}static int get_result(String s) {char arr[] = s.toCharArray();return fun(arr);}public static void main(String[] args) {Scanner sc = new Scanner(System.in);int num = sc.nextInt();sc.nextLine();String[] arr_s=new String [num];for (int i = 0; i < num; i++) {String s = sc.nextLine();arr_s[i]=s;}for (int i = 0; i <num; i++) {System.out.println(get_result(arr_s[i]));}}}