蓝桥杯:填字母游戏(第八届决赛javaB第五题) 博弈+递归+回溯+map记忆化

4 篇文章 0 订阅
2 篇文章 0 订阅

                                                                     历届试题 填字母游戏  

                                                                                                        时间限制:1.0s   内存限制:256.0MB

    

问题描述

  小明经常玩 LOL 游戏上瘾,一次他想挑战K大师,不料K大师说:
  “我们先来玩个空格填字母的游戏,要是你不能赢我,就再别玩LOL了”。


  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

问题分析:

这就是一道博弈的问题,思路比较简单。首先就是模拟过程,当该你填的时候,1.字符串中含有LOL,you lose  -1  2.字符串中没有*号了,同时也不含有LOL ,draw 0     3.如果不是前两种情况,你就要试探的填了  字符串中所有的*号,都可以选填(回溯)

当你选择1个位置的*号时填入L或O,你有三种可能,1.递归函数(改变后的字符串),对手输了,you win 直接返回 1  不用再找下面的了,2,平局,记录一下,继续往下找,因为你想赢,3.对手赢了,you lose,肯定不可能return,继续往下找。如果所有情况都是对手赢,那么你就输了。

 为了提高效率,我加了Map记忆化,但是还是过不了后三组,只得了40分,不过较网上其他的20分代码要有优化,当然主要的是思想。下面是我的代码:



import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;

public class Main {

	static HashMap<String,Integer>map=new HashMap<String, Integer>();
	//过了样例的40%	
	static int isLoL(String s)
	{
		//当我该填数的时候
		if(s.contains("LOL"))
			return -1;
		if(!s.contains("*"))
			return 0;
		
		char arr[]=s.toCharArray();
		boolean drawFlag=false;
		//试探
		for(int i=0;i<arr.length;i++)//主要是为了赢  所以一可以赢(对手输)就return 如果不能
//赢,平局继续走,如果到最后也无法平局即对手都赢(即r=1)那就输了
		{
			if(arr[i]=='*')
			{
					arr[i]='L';
					if(!map.containsKey(new String(arr)))//记忆化
						map.put(new String(arr),isLoL(new String(arr)));
					int r=map.get(new String(arr));
					//System.out.println(i+" L "+r+" "+new String(arr));
					if(r==-1)//下一步该对手了,如果对手输了,你就赢了
						return 1;
					if(r==0)
						drawFlag=true;
					
					arr[i]='O';
					if(!map.containsKey(new String(arr)))
						map.put(new String(arr),isLoL(new String(arr)));
					r=map.get(new String(arr));
					//System.out.println(i+" O "+r+" "+new String(arr));
					if(r==-1)
						return 1;
					if(r==0)
						drawFlag=true;
					arr[i]='*';//回溯
			}
			
		}
		if(drawFlag)
			return 0;
		else
			return -1;
		
	}
	
	
	
	public static void main(String[] args) throws IOException {
		BufferedReader bfr=new BufferedReader(new InputStreamReader(System.in));
		String str=bfr.readLine();
		int n=Integer.parseInt(str);
		for(int i=0;i<n;i++)
		{
			str=bfr.readLine();
			map.clear();
			System.out.println(isLoL(str));
		}
		
	}

}

总结:

1.博弈的思想(试探,回溯)

2.string 和char[] 的转换

String s="123";	
char arr[]=s.toCharArray();
String s1=new String(arr);

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值