2017年第八届蓝桥杯Java程序设计本科B组决赛 填字母游戏(编程大题)

本文详细解析了2017年第八届蓝桥杯Java程序设计本科B组决赛中的一道填字母游戏题目,通过分析游戏规则和双方最优策略,提供了暴力搜索的解题思路,并附带了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2017年第八届蓝桥杯Java程序设计本科B组决赛个人题解汇总:

https://blog.youkuaiyun.com/daixinliangwyx/article/details/90184941

 

第五题

标题:填字母游戏

小明经常玩 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

资源约定:
峰值内存消耗 < 256M
CPU消耗  < 1000ms


请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。


不会正规解法啊啊啊啊啊啊啊啊啊啊

暴力搜索做法:因为双方都会走最优步,因此就按双方走最优步来递归模拟填字母的过程,一直递归下去如果在双方都最优的情况下还能赢,则说明必赢。所以就一直递归搜是否存在必赢局面,如果不存在则考虑平局,平局也不行才返回-1表示必输。很明显会超时,但是可以学习这种想法思路。

20分超时代码:

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.*;


public class Main {
    public static InputReader in = new InputReader(new BufferedInputStream(System.in));
    public static PrintWriter out = new PrintWriter(System.out);
    public static int n;
    public static String s;

    public static void main(String[] args) {
        n = in.nextInt();
        while (n-- > 0) {
            s = in.nextLine();
            out.println(isWin(s));
            out.flush();
        }
        out.close();
    }

    static int isWin(String now) {//轮到当前人来填
        if (now.contains("LOL")) return -1;//当前人还没填,串里面就已经存在LOL了,则当前人输了
        if (now.contains("*") == false) return 0;//没有可以填的格子了且没有LOL子串,平局
        char[] tmp = now.toCharArray();
        int len = now.length(), ping = 0;
        for (int i = 0; i < len; i++) {
            if (now.charAt(i) == '*') {//当前位置可以填
                tmp[i] = 'L';//先填一个'L'
                switch (isWin(new String(tmp))) {
                    case -1:
                        return 1;//下一个人填的时候输了,则表示当前人赢了
                    case 0:
                        ping = 1;//平局,先不直接返回,继续看有没有机会可以赢
                }
                //当填'L'的情况下,下一个人会赢则先不直接返回当前人输,因为当前人是可以在该位置不填'L'而填'O'的,或者不在该位置操作(进入下一次i循环)
                tmp[i] = 'O';
                switch (isWin(new String(tmp))) {
                    case -1:
                        return 1;
                    case 0:
                        ping=1;
                }
                //不在该位置进行操作
                tmp[i] = '*';
            }
        }
        if (ping == 1) return 0;
        return -1;//上面所有可能性都不能得到赢或者平,则当前人必输
    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public String nextLine() {
            String str = null;
            try {
                str = reader.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public Double nextDouble() {
            return Double.parseDouble(next());
        }

        public BigInteger nextBigInteger() {
            return new BigInteger(next());
        }

    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值