蓝桥杯 十一届B组国赛(Java)

本文介绍了如何解决蓝桥杯编程竞赛中的两道题目:本质上升序列和玩具蛇。对于本质上升序列问题,通过遍历所有可能的26个字母升序组合并检查是否能在原始字符串中找到,最终得出答案3616159。而玩具蛇问题中,通过递归枚举蛇头的位置,计算出不同折叠方案的总数,得到答案为552。这两个问题展示了在有限制条件下的序列生成与搜索策略。
摘要由CSDN通过智能技术生成

试题 D: 本质上升序列

问题描述:
小蓝特别喜欢单调递增的事物。
在一个字符串中,如果取出若干个字符,将这些字符按照在字符串中的顺
序排列后是单调递增的,则成为这个字符串中的一个单调递增子序列。
例如,在字符串 lanqiao 中,如果取出字符 n 和 q,则 nq 组成一个单
调递增子序列。类似的单调递增子序列还有 lnq、i、ano 等等。
小蓝发现,有些子序列虽然位置不同,但是字符序列是一样的,例如取第
二个字符和最后一个字符可以取到 ao,取最后两个字符也可以取到 ao。小蓝
认为他们并没有本质不同。
对于一个字符串,小蓝想知道,本质不同的递增子序列有多少个?
例如,对于字符串 lanqiao,本质不同的递增子序列有 21 个。它们分别
是 l、a、n、q、i、o、ln、an、lq、aq、nq、ai、lo、ao、no、io、lnq、
anq、lno、ano、aio。
请问对于以下字符串(共 200 个小写英文字母,分四行显示):(如果你把
以下文字复制到文本文件中,请务必检查复制的内容是否与文档中的一致。在
试题目录下有一个文件 inc.txt,内容与下面的文本相同)
tocyjkdzcieoiodfpbgcncsrjbhmugdnojjddhllnofawllbhf
iadgdcdjstemphmnjihecoapdjjrprrqnhgccevdarufmliqij
gihhfgdcmxvicfauachlifhafpdccfseflcdgjncadfclvfmad
vrnaaahahndsikzssoywakgnfjjaihtniptwoulxbaeqkqhfwl
本质不同的递增子序列有多少个?

解题思路
1: 题目给的问题序列全部遍历需要很长时间,题目要求字符不会重复,并且是升序的,所以这样的序列的所有可能情况最多就是26个英文字母取1个到26个然后排序的所有情况。
2: 所有我遍历26个英文字母能产生的所有情况,将遍历产生的字符串拿到题目给的字符串去提取,看能否从题目的字符串中按序提取出这个字符串的各个字符,能提取就将个数加1.
3: 这样遍历次数从200,减少到了26,很快就能计算出来,验证过题目中的“lanqiao”, 能得出正确答案
4: 最终答案:3616159

import java.util.LinkedList;

/**
 * 〈一句话功能简述〉<br> 
 * 〈蓝桥杯D〉
 */
public class D {
    static char[] questionChar = new char[200];
    static char[] alphabetChar  = new char[26];
    static LinkedList<Character> L = new LinkedList<Character>();  //保存每次递归产生的有序字符序列
    static long count = 0;  //保存最后的个数

    //判断该有序序列 能否在原序列中按序提取
    static boolean judge(LinkedList<Character> L){
        int index=0;
        for(int i=0; i<questionChar.length; i++) {
            if(questionChar[i] == L.get(index).charValue()){
                index++;
                if(index>=L.size()) return true;
            }
        }
        return false;
    }
    
    //递归提取end 个字符的所有情况
    static void solve(int begin, int end, int select){    //select 表示这一次递归从哪个字符开始取, begin表示这是第几次递归,end表示总共需要递归几次,也就是这个提取的字符串需要有几个字符
        if(begin>end){
            if (judge(L)) count++;

        }else{
            for(int i=select; i<alphabetChar.length; i++){
                    L.add(alphabetChar[i]);
                    solve(begin + 1, end, i + 1);  //之后每一次递归都从前一个字符的后面开始取,因为遍历序列是
                                                                // “abcdef.....”, 所以这样可以直接保证提取出来的是有序字符
                    L.remove(L.size() - 1);
            }
        }
    }

    //主函数
    public static void main(String[] args){

        String question = "tocyjkdzcieoiodfpbgcncsrjbhmugdnojjddhllnofawllbhf" +
                      "iadgdcdjstemphmnjihecoapdjjrprrqnhgccevdarufmliqij" +
                      "gihhfgdcmxvicfauachlifhafpdccfseflcdgjncadfclvfmad" +
                      "vrnaaahahndsikzssoywakgnfjjaihtniptwoulxbaeqkqhfwl";
        
        String alphabet = "abcdefghijklmnopqrstuvwxyz";  //遍历这个字母序列的可以产生的所有升序序列
        for(int i=0; i<alphabet.length(); i++){
            alphabetChar[i] = alphabet.charAt(i);
        }
        for(int i=0; i<question.length(); i++){
            questionChar[i] = question.charAt(i);      //将字符串保存到字符数组中,方便遍历
        }
        for(int i=1; i<=26; i++){
            solve(1, i, 0);   
        }
        System.out.println(count);
    }
}

试题E:玩具蛇

【问题描述】
小蓝有一条玩具蛇,一共有 16 节,上面标着数字 1 至 16。每一节都是一
个正方形的形状。相邻的两节可以成直线或者成 90 度角。
小蓝还有一个 4 × 4 的方格盒子,用于存放玩具蛇,盒子的方格上依次标着
字母 A 到 P 共 16 个字母。
小蓝可以折叠自己的玩具蛇放到盒子里面。他发现,有很多种方案可以将
玩具蛇放进去。
下图给出了两种方案:
请帮小蓝计算一下,总共有多少种不同的方案。如果两个方案中,存在玩
具蛇的某一节放在了盒子的不同格子里,则认为是不同的方案。

解题思路: 1的存放位置依次枚举,后续的采用DFS,因为每一个后续的数字可能存放的位置都是前一个数字位置的上下左右
答案 552

import java.util.*;
/**
 * 〈蓝桥杯模拟E〉
 */
public class E {
    static int[][] a = new int[4][4];
    static int count = 0; //保存最终的种类
    
    static void solve(int x, int y, int next, int num){
        if(num>16) {
            count++;
        }
        else{
            if(x-1>=0 && a[x-1][y]==0){
                a[x-1][y] = next;
                solve(x-1, y, next+1, num+1);
                a[x-1][y] = 0;
            }
            if(x+1<=3 && a[x+1][y]==0){
                a[x+1][y] = next;
                solve(x+1, y, next+1, num+1);
                a[x+1][y] = 0;
            }
            if(y-1>=0 && a[x][y-1]==0){
                a[x][y-1] = next;
                solve(x, y-1, next+1, num+1);
                a[x][y-1] = 0;
            }
            if(y+1<=3 && a[x][y+1]==0){
                a[x][y+1] = next;
                solve(x,y+1, next+1, num+1);
                a[x][y+1] = 0;
            }
        }
    }
    //主函数
    public static void main(String[] args){

        for(int i=0; i<4; i++){
            for(int j=0; j<4; j++){
                for(int m=0; m<4; m++){
                    Arrays.fill(a[m],0);
                }
                a[i][j] = 1;
                solve(i, j, 2, 2);
            }
        }
        System.out.println(count);
    }
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值