蓝桥杯试题
试题 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);
}
}