蓝桥杯2015国赛javaB组题目详解


蓝桥杯2015国赛javaB组题目详解


第一题 积分之谜

题目描述:

小明开了个网上商店,卖风铃。共有3个品牌:ABC。    
为了促销,每件商品都会返固定的积分。  
小明开业第一天收到了三笔订单:  
第一笔:3A + 7B + 1C,共返积分:315  
第二笔:4A + 10B + 1C,共返积分:420  
第三笔:A + B + C,共返积分...    
你能算出第三笔订单需要返积分多少吗?

解析:

3a+7b+c=315
4a+10b+c=420
可以解出
a+b+c=105

第二题 完美正方形

题目描述:

如果一些边长互不相同的正方形,可以恰好拼出一个更大的正方形,   
则称其为完美正方形。
历史上,人们花了很久才找到了若干完美正方形。
比如:如下边长的22个正方形
2 3 4 6 7 8 12 13 14 15 16 17 18 21 22 23 24 26
27 28 50 60
如下图img-1那样组合,就是一种解法。此时,
紧贴上边沿的是:60 50
紧贴下边沿的是:26 28 17 21 18

img-1

22阶完美正方形一共有8种。下面的组合是另一种:
2 5 9 11 16 17 19 21 22 24 26 30 31 33 35 36 41 46 47 50 52 61
如果告诉你该方案紧贴着上边沿的是从左到右依次为:47 46 61
你能计算出紧贴着下边沿的是哪几个正方形吗?

解析:

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;


public class 蓝桥杯2015完美正方形 {
    static class Node{
        int x ;
        int y ;
        public Node(int x ,int y){
            this.x = x;
            this.y = y;
        }
    }

    public static void main(String[] args) {
        int N=154;
        int[][] graph = new int[N+1][N+1];
        //正方形块数组
        int[] number = {2,5,9,11,16,17,19,21,22,24,26,30,31,33,35,36,41,50,52};
        //init
        for(int i=1;i<=154;i++){
            for(int j=1;j<=46;j++){
                graph[j][i]=1;
            }
        }
        for(int i=1;i<=47;i++){
            graph[47][i]=1;
        }
        for(int i=47;i<=61;i++){
            for(int j=94;j<=154;j++){
                graph[i][j]=1;
            }
        }

        //开始dfs
        select(graph, number);
    }
    static  Stack<Integer> stack = new Stack<>();
    static  List<String> path = new ArrayList<>();
    public static void select(int[][] graph,int[] number){
    if(stack.size()==number.length){
        System.out.println(path.toString());
        System.out.println(stack);
        return;
    }
       
    for(int n=0;n<number.length;n++){
    //先找到可以插入的点
    Node myNode = find(graph);
        if(myNode!=null){
            if(!stack.contains(number[n])&& yvejie(graph, myNode.x, myNode.y, number[n])){
                stack.push(number[n]);
                //记录路径
                path.add("("+myNode.x+","+myNode.y+")");
                //graph填充
                tianchong(myNode.x, myNode.y, graph, number[n]);
                //寻找下一个
                select(graph, number);

                //无果出栈
                stack.pop();
                //清除之前错误的填充
                qingchu(myNode.x, myNode.y, graph, number[n]);
                //清除之前错误的路径
                path.remove(path.size()-1);
            }
        }
    }
    return;
    }
    //找到可以插入的NODE
    public static Node find(int[][] graph){
        for(int i=1;i<graph.length;i++){
            for(int j=1;j<graph.length;j++){
                if(graph[j][i]==0){
                    return new Node(i, j);
                }
            }
        }
        return null;
    }
    //判断是否越界
    public static Boolean yvejie(int[][] graph,int x,int y,int number) {
        if(number>graph.length-x||number>graph.length-y){
            return false;
        }
        for(int m=x;m<x+number;m++){
            for(int n=y;n<y+number;n++){
                if(graph[m][n]==1){
                    return false;
                }
            }
        }
        return true;
    }
    //对可行区域进行填充
    public static void tianchong(int x,int y,int[][] graph,int number) {
        for(int m=x;m<x+number;m++){
            for(int n=y;n<y+number;n++){
                graph[m][n]=1;
            }
        }
    }
    //对尝试过的不可行区域的填充进行一个撤销
    public static void qingchu(int x,int y,int[][] graph,int number) {
        for(int m=x;m<x+number;m++){
            for(int n=y;n<y+number;n++){
                graph[m][n]=0;
            }
        }
    }
}
注释写的很清楚了
其实还可以优化一下,就是可以对正方形块进行一个排序  
然后只要小的都越界大的就不用看了

具体操作为:

对排序过后的number数组进行遍历  
在判断是否越界的if的后面添加一个else  
加入return就行了
要想输出结果更加直观可以考虑path记录四个点的左边而不是一个  
最后就很容易找到最下面的正方形

第三题 密文搜索

题目描述

福尔摩斯从X星收到一份资料,全部是小写字母组成。
他的助手提供了另一份资料:许多长度为8的密码列表。
福尔摩斯发现,这些密码是被打乱后隐藏在先前那份资料中的。
请你编写一个程序,从第一份资料中搜索可能隐藏密码的位置。
要考虑密码的所有排列可能性。

输入格式

输入第一行:一个字符串s,全部由小写字母组成,长度小于1024*1024
紧接着一行是一个整数n,表示以下有n行密码,1<=n<=1000
紧接着是n行字符串,都是小写字母组成,长度都为8

输出格式

一个整数, 表示每行密码的所有排列在s中匹配次数的总和。

输入样例

aaaabbbbaabbcccc
2
aaaabbbb
abcabccc

输出样例

4

数据范围与提示

第一个密码匹配了3次,第二个密码匹配了1次,一共4次。

思路步骤

  • 对字符串s进行处理从头到尾每8位截取一段,每段按照ASSIC从小到大排序后保存
  • 对每一个密码串按照ASSIC从小到大排序
  • 遍历比较

代码实现

import java.util.Arrays;
import java.util.HashMap;
import java.util.Scanner;

public class 蓝桥杯2015密文搜索 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.next();
        int N = sc. nextInt();
        String[] s = new String[N];
        for(int i=0;i<N;i++){
            char[] mymid = sc.next().toCharArray();
            //转数组排序
            Arrays.sort(mymid);
            //转字符串保存
            s[i] = String.valueOf(mymid);
        }
        sc.close();
        HashMap<Integer,String> map = new HashMap<>();
        StringBuilder sb = new StringBuilder(str);
        int flag=0;
        //字符串切割
        while(true){
            if(flag+7>str.length()-1){
                break;
            }
            if(flag+7<=str.length()-1){
                //substring包前不包后
                String mysb = sb.substring(flag, flag+8);
                char[] mych = mysb.toCharArray();
                Arrays.sort(mych);
                map.put(flag,String.valueOf(mych));
            }
            flag++;
        }
        int count=0;
        for(String st:map.values()){
            for(String mima:s){
                //记得用equals
                if(st.equals(mima)){
                    count++;
                }
            }
        }
        System.out.println(count);
    }

}

文章作者: Lao Wu
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Lao Wu !
评论
  目录