蓝桥杯2017真题 | java组

1、迷宫 

public class Main {
  static int count = 0;
    public static void main(String[] args) {
        char[][] ch = {
                { 'U', 'D', 'D', 'L', 'U', 'U', 'L', 'R', 'U', 'L' },
                { 'U', 'U', 'R', 'L', 'L', 'L', 'R', 'R', 'R', 'U' },
                { 'R', 'R', 'U', 'U', 'R', 'L', 'D', 'L', 'R', 'D' },
                { 'R', 'U', 'D', 'D', 'D', 'D', 'U', 'U', 'U', 'U' },
                { 'U', 'R', 'U', 'D', 'L', 'L', 'R', 'R', 'U', 'U' },
                { 'D', 'U', 'R', 'L', 'R', 'L', 'D', 'L', 'R', 'L' },
                { 'U', 'L', 'L', 'U', 'R', 'L', 'L', 'R', 'D', 'U' },
                { 'R', 'D', 'L', 'U', 'L', 'L', 'R', 'D', 'D', 'D' },
                { 'U', 'U', 'D', 'D', 'U', 'D', 'U', 'D', 'L', 'L' },
                { 'U', 'L', 'R', 'D', 'L', 'U', 'U', 'R', 'R', 'R' }
        };
        for (int i = 0; i < ch.length; i++) {
            for (int j = 0; j < ch[i].length; j++) {
                dfs(i, j, ch);
            }
        }
        System.out.println(count);

    }

    public static void dfs(int x, int y, char[][] ch) {
        int m = ch.length;
        int n = ch[0].length;
       
        if (x < 0 || y < 0 || x > m - 1 || y > n - 1) {
            count++;
      
            return;
        }
        char flag = ch[x][y];
        if (ch[x][y]=='p') {
            return;
        }
        ch[x][y] = 'p';
        if (flag == 'U') {
            dfs(x-1, y, ch);
        }
        if (flag =='L') {
            dfs(x, y-1, ch);
        }
        if (flag=='D') {
            dfs(x+1, y, ch);
        }
        if (flag =='R') {
            dfs(x, y+1, ch);
        }
       
        ch[x][y] = flag;
    }
}

总结:A组今年第一题就这么恶心,没做出来直接看题解,是道dfs,但是中间要检测是否走过,走过的直接退出,这里用了一个flag变量来标记,刚进来就记录原本的方向,然后赋值成P标识走过了,如果下次进来if成立为p就直接return,说明走过了,然后返回上一层把flag赋值回去(递归的时候每层的变量都是独立的 所以不存在下层的flag会吧上层覆盖,所以我们层都用自己的flag记录

2、9数算式

观察如下的算式:

9213×85674=789314562

左边的乘数和被乘数正好用到了 11 ~ 99 的所有数字,每个 11 次。 而乘积恰好也是用到了 11 ~ 99 的所有数字,并且每个 11 次。

请你借助计算机的强大计算能力,找出满足如上要求的 99 数算式一共有多少个?

注意:

  1. 总数目包含题目给出的那个示例。
  2. 乘数和被乘数交换后作为同一方案来看待。
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
import java.util.HashSet;
//import java.util.Scanner;
import java.util.Set;

public class Main {
    private static int[] a = {1,2,3,4,5,6,7,8,9};
    private static int ans;
    public static void main(String[] args) {
//        Scanner scan = new Scanner(System.in);
//        f(0);
//        System.out.println(ans);
        System.out.println(3250/2);
//        scan.close();
    }
    private static void f(int k) {
        if(k == 9) {
            for (int i = 1; i < 9; i++) {
                check(i);
            }
        }
        for (int i = k; i < a.length; i++) {
            int t = a[i];
            a[i] = a[k];
            a[k] = t;
            
            f(k+1);
            
            t = a[i];
            a[i] = a[k];
            a[k] = t;
        }
        
    }
    private static void check(int len) {
        int num1 =0;
        int num2 = 0;
        int t = 1;
        for (int i = len-1; i >= 0; i--) {
            num1 += a[i]*t;
            t*=10;
        }
        t = 1;
        for (int i = a.length-1; i >= len; i--) {
            num2 += a[i]*t;
            t*=10;
        }
        int num3 = num1*num2;

        String str = num3+"";
        if(str.length()!=9)return;
        Set<Character> set = new HashSet<>();
        for (int i = 0; i < str.length(); i++) {
            if (str.charAt(i)!='0') {
                set.add(str.charAt(i));
            }
            
        }
        if(set.size() == 9) {
            ans++;
//            System.out.printf("%d * %d == %d\n",num1,num2,num3);
        }
    }
}

总结:全排列,但是这个check比较难 第一个for是前面的数字,第二个是后面的数,然后相乘为9位数字而且不重复,就能ans++(放到set里面看有没有重复)

3、字母组串

由 A,B,C 这3个字母就可以组成许多串。 比如:"A","AB","ABC","ABA","AACBB" ....填空

现在,小明正在思考一个问题: 如果每个字母的个数有限定,能组成多少个已知长度的串呢?

他请好朋友来帮忙,很快得到了代码, 解决方案超级简单,然而最重要的部分却语焉不详。

{
    // a个A,b个B,c个C 字母,能组成多少个不同的长度为n的串。
    static int f(int a, int b, int c, int n)
    {
        if(a<0 || b<0 || c<0) return 0;
        if(n==0) return 1; 
        
        return ________________________________;  //填空
    }
    
    public static void main(String[] args)
    {
        System.out.println(f(1,1,1,2));
        System.out.println(f(1,2,3,3));
    }
}

答案:f(a-1,b,c,n-1)+f(a,b-1,c,n-1)+f(a,b,c-1,n-1)

总结:看到这种最后小于0的肯定是递归的递减,有3种情况,a减少,b减少,c减少然后把他们的数量相加就是各种情况的总和。

4、最大公共子串

最大公共子串长度问题就是: 求两个串的所有子串中能够匹配上的最大长度是多少。

比如:"abcdkkk" 和 "baabcdadabc", 可以找到的最长的公共子串是"abcd",所以最大公共子串长度为 4。下面的程序是采用矩阵法进行求解的,这对串的规模不大的情况还是比较有效的解法。

请分析该解法的思路,并补全划线部分缺失的代码。填空

import java.util.Scanner;
public class Main
{
    static int f(String s1, String s2)
    {
        char[] c1 = s1.toCharArray();
        char[] c2 = s2.toCharArray();
        
        int[][] a = new int[c1.length+1][c2.length+1];
        
        int max = 0;
        for(int i=1; i<a.length; i++){
            for(int j=1; j<a[i].length; j++){
                if(c1[i-1]==c2[j-1]) {
                    a[i][j] = __________________________; 
                    if(a[i][j] > max) max = a[i][j];
                }
            }
        }
        
        return max;
    }
    
    public static void main(String[] args){
        int n = f("abcdkkk", "baabcdadabc");
        System.out.println(n);
        System.out.println(f("aaakkkabababa", "baabababcdadabc"));
        System.out.println(f("abccbaacbcca", "ccccbbbbbaaaa"));
        System.out.println(f("abcd", "xyz"));
        System.out.println(f("ab", "ab"));
        
    }
}

答案:a[i-1][j-1]+1

总结:这题是动态规划,新的东西用到旧的,根据题大概可以理解到他是竖着遍历第一个字符串,横着遍历第二个,连续相等的话是斜着加的。从而可以推出当元素连续相等的时候,后面右下角的等于右上角元素加1。

5、购物单

小明刚刚找到工作,老板人很好,只是老板夫人很爱购物。老板忙的时候经常让小明帮忙到商场代为购物。小明很厌烦,但又不好推辞。

这不,大促销又来了!老板夫人开出了长长的购物单,都是有打折优惠的。

小明也有个怪癖,不到万不得已,从不刷卡,直接现金搞定。

现在小明很心烦,请你帮他计算一下,需要从取款机上取多少现金,才能搞定这次购物。

取款机只能提供 100100 元面额的纸币。小明想尽可能少取些现金,够用就行了。 你的任务是计算出,小明最少需要取多少现金。

以下是让人头疼的购物单,为了保护隐私,物品名称被隐藏了。

****     180.90       88折
****      10.25       65折
****      56.14        9折
****     104.65        9折
****     100.30       88折
****     297.15        半价
****      26.75       65折
****     130.62        半价
****     240.28       58折
****     270.62        8折
****     115.87       88折
****     247.34       95折
****      73.21        9折
****     101.00        半价
****      79.54        半价
****     278.44        7折
****     199.26        半价
****      12.97        9折
****     166.30       78折
****     125.50       58折
****      84.98        9折
****     113.35       68折
****     166.57        半价
****      42.56        9折
****      81.90       95折
****     131.78        8折
****     255.89       78折
****     109.17        9折
****     146.69       68折
****     139.33       65折
****     141.16       78折
****     154.74        8折
****      59.42        8折
****      85.44       68折
****     293.70       88折
****     261.79       65折
****      11.30       88折
****     268.27       58折
****     128.29       88折
****     251.03        8折
****     208.39       75折
****     128.88       75折
****      62.06        9折
****     225.87       75折
****      12.89       75折
****      34.28       75折
****      62.16       58折
****     129.12        半价
****     218.37        半价
****     289.69        8折

需要说明的是,8888 折指的是按标价的 88%88 计算,而 88 折是按 80%80 计算,余者类推。 特别地,半价是按 50%50 计算。

请输出小明要从取款机上提取的金额,单位是元。

题解:这题考得就是excel的使用,我们直接算太慢了,最快的就是用excel表格。

6、纸牌三角形

A,2,3,4,5,6,7,8,9 共 99 张纸牌排成一个正三角形(AA 按 11 计算)。要求每个边的和相等。 下图就是一种排法。

这样的排法可能会有很多。

如果考虑旋转、镜像后相同的算同一种,一共有多少种不同的排法呢?

请你计算并提交该数字。

import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    static int ans =0;
    static int[] a = {1,2,3,4,5,6,7,8,9};
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //在此输入您的代码...
        fun(0);
        System.out.println(ans/6);
        scan.close();
    }
    static void fun(int start)
    {
      if(start==a.length){
        if(check()){
          ans++;
        }
      }
      for(int i =start;i<a.length;i++){
        int temp = a[start];
        a[start] = a[i];
        a[i] = temp;
        fun(start+1);
        temp = a[start];
        a[start] = a[i];
        a[i] = temp;
      }
    }
    static boolean check()
    {
      int x1 =a[0]+a[1]+a[2]+a[3];
      int x2 =a[3]+a[4]+a[5]+a[6];
      int x3 =a[6]+a[7]+a[8]+a[0];
      if(x1==x2&&x2==x3)
      {
        return true;
      }
      return false;
    }
}

总结:全排列。固定模板,但是有坑,他旋转和对称都算一种,那么对称要除2,旋转又有3种情况,所有ans一共要除以6

7、取位数

求1个整数的第k位数字有很多种方法。 以下的方法就是一种。填空

import java.util.*;
public class Main
{
    static int len(int x){
        if(x<10) return 1;
        return len(x/10)+1;
    }
    
    // 取x的第k位数字
    static int f(int x, int k){
        if(len(x)-k==0) return x%10;
        return ______________________;  //填空
    }
    
    public static void main(String[] args)
    {
        int x = 23513;
        //System.out.println(len(x));
        System.out.println(f(x,3));
        System.out.println(f(893275,2));
    }
}

答案:f(x/10,k)

总结:当len(x)-k==0才return,大概率递归,递归要满足这个条件只能len减小或k变大,k是固定的,所以只能len(x)减小了,所以每次减小x/10,k不变

8、分巧克力

儿童节那天有 K 位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。

小明一共有 NN 块巧克力,其中第 ii 块是 H_i \times WiHi​×Wi 的方格组成的长方形。为了公平起见,

小明需要从这 NN 块巧克力中切出 K 块巧克力分给小朋友们。切出的巧克力需要满足:

  1. 形状是正方形,边长是整数;

  2. 大小相同;

例如一块 6x5 的巧克力可以切出 6 块 2x2 的巧克力或者 2 块 3x3 的巧克力。

当然小朋友们都希望得到的巧克力尽可能大,你能帮小明计算出最大的边长是多少么?

输入描述

第一行包含两个整数 N,KN,K (1 \leq N, K \leq 10^51≤N,K≤105)。

以下 N 行每行包含两个整数 H_i,W_iHi​,Wi​ (1 \leq H_i, W_i \leq 10^51≤Hi​,Wi​≤105)。

输入保证每位小朋友至少能获得一块 1x1 的巧克力。

输出描述

输出切出的正方形巧克力最大可能的边长。

输入输出样例

输入

2 10
6 5
5 6

输出

2
public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        int k = scan.nextInt();
        int[][] nums = new int[n][2];

        for (int i = 0; i < n; i++) {
            nums[i][0]= scan.nextInt();
            nums[i][1]= scan.nextInt();
        }

        int left = 1,right = 100000;
        while (left < right) {
            int mid = left + (right - left + 1) / 2;
            int count = 0;
            for (int i = 0; i < n; i++) {
                count+=(nums[i][0]/mid) * (nums[i][1]/mid);
            }
            if (count < k) {
                right = mid - 1;
            }else left = mid;
        }
        System.out.println(left);
    }
}

总结:暴力枚举题,枚举切的边长,当最后切出来的块数大于等于人数,就返回。我们可以优化为二分查找。

9、杨辉三角

杨辉三角也叫帕斯卡三角,在很多数量关系中可以看到,十分重要。

第0行:           1
第1行:          1 1
第2行:         1 2 1
第3行:        1 3 3 1
第4行:       1 4 6 4 1
....

两边的元素都是1, 中间的元素是左上角的元素与右上角的元素和。

我们约定,行号,列号都从 0 计数。所以: 第 6 行的第 2 个元素是 15,第 3 个元素是 20。

直观地看,需要开辟一个二维数组,其实一维数组也可以胜任。 如下程序就是用一维数组“腾挪”的解法。填空

import java.util.Scanner;
public class Main
{
    // 杨辉三角形的第row行第col列
    static long f(int row, int col){
        if(row<2) return 1;
        if(col==0) return 1;
        if(col==row) return 1;
        
        long[] a = new long[row+1];
        a[0]=1;
        a[1]=1;
        
        int p = 2;
        
        while(p<=row){
            a[p] = 1;
            for( _________________ ) a[q] = a[q] + a[q-1];
            p++;
        }
        
        return a[col];
    }
    
    public static void main(String[] args){
        System.out.println(f(6,2));
        System.out.println(f(6,3));
        System.out.println(f(40,20));
        
    }
}

答案:int q=p-1;q>=1;q--

总结:从上面可以看出来while循环是循环第几行,里面的for是为了遍历行内的元素,根据题目提示现在这个就是之前的a[q]+a[q-1],所以每次就是遍历这个q,我们要逆序遍历,为了不影响到下一次遍历

10、Excel地址

Excel 单元格的地址表示很有趣,它使用字母来表示列号。

比如,

A 表示第 1 列,

B 表示第 2 列,

Z 表示第 26 列,

AA 表示第 27 列,

AB 表示第 28 列,

BA 表示第 53 列,

当然 Excel 的最大列号是有限度的,所以转换起来不难。

如果我们想把这种表示法一般化,可以把很大的数字转换为很长的字母序列呢?

本题目即是要求对输入的数字, 输出其对应的 Excel 地址表示方式。

输入描述

输入一个整数 nn,其范围 [1,2147483647]。

输出描述

输出 nn 对应的 Excel 地址表示方式。

输入输出样例

示例

输入

26

输出

Z
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n=in.nextInt();
        String str="";
        for(int s;n!=0;n/=26){
            if(n%26==0) {
                n-=26;
                s=26;
            }else {
                s=n%26;
            }
            str=(char)(s+64)+str;
        }
        System.out.print(str);
        in.close();
    }
}

总结:有点类似进制转换,循环每次都除26,除26前取余,然后记录余数,最后把他们字符串拼接起来,前面的余数在后面所以是str=(char)(s+64)+str; 其中如果除26==0就让s==26因为没有0这个对应的字母26就是z,然后n要减去26

11、日期问题

小明正在整理一批历史文献。这些历史文献中出现了很多日期。小明知道这些日期都在 1960 年 1 月 1 日至 2059 年 12 月 31 日。令小明头疼的是,这些日期采用的格式非常不统一,有采用年/月/日的,有采用月/日/年的,还有采用日/月/年的。

更加麻烦的是,年份也都省略了前两位,使得文献上的一个日期,存在很多可能的日期与其对应。

比如 02/03/04,可能是 2002 年 03 月 04 日、2004 年 02 月 03 日或 2004 年 03 月 02 日。

给出一个文献上的日期,你能帮助小明判断有哪些可能的日期对其对应吗?

输入描述

一个日期,格式是 "AA/BB/CCAA/BB/CC" (0 \leq A, B, C \leq 90≤A,B,C≤9)。

输出描述

输出若干个不相同的日期,每个日期一行,格式是 "yyyy-MM-ddyyyy−MM−dd"。多个日期按从早到晚排列。

输入输出样例

示例

输入

02/03/04

输出

2002-03-04
2004-02-03
2004-03-02
package saunfati;

import java.text.SimpleDateFormat;
import java.util.Scanner;
import java.util.TreeSet;

public class 日期问题 {

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		String temp = scanner.next();
		String date[] = temp.split("/");
		String y = date[0];
		String m = date[1];
		String d = date[2];
		String a = (Integer.parseInt(y)<60?"20"+y:"19"+y)+"-"+m+"-"+d;
		String b = (Integer.parseInt(d)<60?"20"+d:"19"+d)+"-"+y+"-"+m;
		String c = (Integer.parseInt(d)<60?"20"+d:"19"+d)+"-"+m+"-"+y;
		
		TreeSet<String> set = new TreeSet<String>();
		if(f(a)) set.add(a);
		if(f(b)) set.add(b);
		if(f(c)) set.add(c);
		for(Object object:set) {
			System.out.println(object);
		}
	}
	static boolean f(String date) {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		format.setLenient(false);
		try {
			format.parse(date);
		}catch(Exception e) {
			return false;
		}
		return true;
	}

}

总结:本地可以用TreeSet来做到去重排序。而且可以用SimpleDateFormat的setLenient方法来判断日期是否有效的。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卒获有所闻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值