蓝桥杯31天真题冲刺|题解报告|第十一天

大家好,我是snippet,今天是刷蓝桥真题的第十一天,今天的知识包含gcd,动态规划,这段时间我们也学了很多新知识,要及时巩固,下面是我今天的题解

目录

一、卡片

二、路径

三、字符统计

四、费用报销 


一、卡片

题目链接:卡片 - 蓝桥云课 (lanqiao.cn)

题目内容:

题目描述

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

小蓝有很多数字卡片,每张卡片上都是数字 0 到 9。

小蓝准备用这些卡片来拼一些数,他想从 1 开始拼出正整数,每拼一个,就保存起来,卡片就不能用来拼其它数了。

小蓝想知道自己能从 11 拼到多少。

例如,当小蓝有 30 张卡片,其中 0 到 9 各 3 张,则小蓝可以拼出 1 到 10,

但是拼 11 时卡片 1 已经只有一张了,不够拼出 11。

现在小蓝手里有 0 到 99 的卡片各 2021 张,共 20210 张,请问小蓝可以从 11 拼到多少?

提示:建议使用计算机编程解决问题。

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M

解题思路:

先用一个数组存1-9每个数字含有的个数(2021),从数字1开始遍历,当1-9哪个数字用完的时候,我们就输出遍历到的那个数的前一个数,因为拼这个数的字符已经不够了

代码:

package 蓝桥杯31天真题冲刺.Day11;

import java.util.Arrays;

/**
 * @author snippet
 * @data 2023-03-14
 * 卡片-蓝桥云课
 */
public class T1_卡片 {

    static int[] a = new int[10];

    static int check(int n) {
        int k = n;
        while (k > 0) {
            int t = k % 10;
            if (a[t] <= 0) return n-1;
            a[t]--;
            k /= 10;
        }
        return -1;
    }

    public static void main(String[] args) {
        Arrays.fill(a, 2021);
        for (int i = 1; ;i++) {
            if (check(i) != -1) {
                System.out.println(check(i));
                return;
            }
        }
    }
}

二、路径

题目链接:路径 - 蓝桥云课 (lanqiao.cn)

题目内容:

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

小蓝学习了最短路径之后特别高兴,他定义了一个特别的图,希望找到图 中的最短路径。

小蓝的图由 2021 个结点组成,依次编号 1 至 2021。

对于两个不同的结点 a, b,如果 a 和 b 的差的绝对值大于 21,则两个结点 之间没有边相连;如果 a 和 b 的差的绝对值小于等于 21,则两个点之间有一条 长度为 a 和 b 的最小公倍数的无向边相连。

例如:结点 1 和结点 23 之间没有边相连;结点 3 和结点 24 之间有一条无 向边,长度为 24;结点 15 和结点 25 之间有一条无向边,长度为 75。

请计算,结点 1 和结点 2021 之间的最短路径长度是多少。

提示:建议使用计算机编程解决问题。

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M

解题思路:

这个题考察的是gcd和动态规划,从1开始遍历,每次的遍历判断区间为21,当num数组未赋初始值的时候记得赋给初始值,状态转移式为:num[j] = Math.min(num[j], (i*j)/gcd(i,j) + num[i]);

代码:

package 蓝桥杯31天真题冲刺.Day11;

/**
 * @author snippet
 * @data 2023-03-14
 * 路径-蓝桥云课
 */
// 01背包+gcd
public class T2_路径 {

    static int[] num = new int[2022];

    public static void main(String[] args) {
        for (int i = 1; i <= 2021; i++) {
            for (int j = i+1; j <= i+21; j++) {
                if (j == 2022) break;
                if (num[j] == 0) {
                    // 初始化
                    num[j] = num[i] + (i*j)/gcd(i,j);
                } else {
                    num[j] = Math.min(num[j], (i*j)/gcd(i,j) + num[i]);
                }

            }
        }
        System.out.println(num[2021]);
    }

    // 求最大公约数
    static int gcd(int a, int b) {
        return b != 0 ? gcd(b, a%b): a;
    }
}

三、字符统计

题目链接:字符统计 - 蓝桥云课 (lanqiao.cn)

题目内容:

问题描述

给定一个只包含大写字母的字符串 S, 请你输出其中出现次数最多的字符。

如果有多个字母均出现了最多次, 按字母表顺序依次输出所有这些字母。

输入格式

一个只包含大写字母的字符串 S.

输出格式

若干个大写字母,代表答案。

样例输入

 BABBACAC

样例输出

AB

评测用例规模与约定

对于 100% 的评测用例, 1≤∣S∣≤10^6.

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 512M

解题思路:

记录字符的使用次数,并且输出使用次数最大的所有字符,我们用一个一维数组来记录每个字符的使用次数,用一个max来记录字符的最大使用次数即可

代码:

package 蓝桥杯31天真题冲刺.Day11;

import java.io.*;

/**
 * @author snippet
 * @data 2023-03-14
 * 字符统计-蓝桥云课
 */
public class T3_字符统计 {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));

    static int[] c = new int[26];
    static int maxs = 0;

    public static void main(String[] args) throws IOException {
        String s = br.readLine().split(" ")[0];
        for (int i = 0; i < s.length(); i++) {
            int t = ++c[s.charAt(i)-'A'];
            maxs = Math.max(maxs, t);
        }
        for (int i = 0; i < c.length; i++) {
            if (c[i] == maxs) {
                pw.print((char) (i+'A'));
            }
        }
        pw.flush();
        br.close();
    }
}

四、费用报销 

题目链接:费用报销 - 蓝桥云课 (lanqiao.cn)

题目内容:

问题描述

小明在出差结束后返回了公司所在的城市, 在填写差旅报销申请时, 粗心 的小明发现自己弄丢了出差过程中的票据。

为了弥补小明的损失, 公司同意小明用别的票据进行报销, 但是公司财务 要求小明提交的票据中任意两张的日期差不小于 K 天, 且总金额不得超过实际 差旅费用 M 。

比如财务要求 K=7 时, 若小明提交了一张 1 月 8 日的票据, 小明就不能 提交 1 月 2 日至 1 月 14 日之间的其他票据, 1 月 1 日及之前和 1 月 15 日及之 后的票据则可以提交。

公司的同事们一起给小明凑了 N 张票据, 小明现在想要请你帮他整理一 下, 从中选取出符合财务要求的票据, 并使总金额尽可能接近 M 。

需要注意, 由于这些票据都是同一年的, 因此 12 月底的票据不会影响到 1 月初票据的提交。这一年不是闰年。

输入格式

第 1 行: 3 个整数,N,M,K

第 2…N+1 行: 每行 3 个整数mi​,di​,vi​, 第 i+1 行表示第 i 张票据时间 的月份 mi​ 和日期 di​,vi​ 表示该票据的面值

输出格式

第 1 行: 1 个整数, 表示小明能够凑出的最大报销金额

样例输入

4 16 3

1 1 1

1 3 2

1 4 4

1 6 8

样例输出

10

样例说明

选择 1 月 3 日和 1 月 6 日的票据

评测用例规模与约定

对于 100%100% 的评测用例, 1≤N≤1000,1≤M≤5000,1≤K≤50,1≤mi​≤ 12,1≤di​≤31,1≤vi​≤400

日期保证合法。

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 512M

解题思路:

这个题的话,我也还有一点迷茫,看了怂佬的Java题解后,有点顿悟的感觉,也就跟之前写的动态规划的题目差不多,先根据一个条件进行排序(这个题根据日期的天数进行排序),再寻找需要状态转移的区间(对每个物品进行一次放入 同时判断可以放入的票据的区间),最后找到状态转移式以及进行状态转移的条件

代码:

package 蓝桥杯31天真题冲刺.Day11;

import java.io.*;
import java.util.Arrays;
import java.util.Comparator;

/**
 * @author snippet
 * @data 2023-03-14
 * 费用报销-蓝桥云课
 */
// 动态规划-01背包
public class T4_费用报销 {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));

    static int N,M,K;// N表示票据的张数 M表示最大的差旅费用 K表示任意两张票据的最小日期差
    static int[] m = {0,31,28,31,30,31,30,31,31,30,31,30,31};// 一维数组m存每个月的天数
    static int[][] arr = new int[1010][2];// 二维数组arr每行的第一列存该票据的时长 第二列表示该票据的面值
    static boolean[][] dp = new boolean[1010][5050];// 二维数组dp表示前i张票可以组成的最大m值

    public static void main(String[] args) throws IOException {
        String[] s = br.readLine().split(" ");
        N = Integer.parseInt(s[0]);
        M = Integer.parseInt(s[1]);
        K = Integer.parseInt(s[2]);
        for (int i = 1; i <= 12; i++) {
            m[i] += m[i-1];
        }
        for (int i = 1; i <= N; i++) {
            s = br.readLine().split(" ");
            arr[i][0] = m[Integer.parseInt(s[0])-1]+Integer.parseInt(s[1]);
            arr[i][1] = Integer.parseInt(s[2]);
        }
        // 按照时间排序
        Arrays.sort(arr, 1, N+1, Comparator.comparingInt(a -> a[0]));
        // 初始化
        dp[0][0] = true;
        int left = 0;
        int max = 0;
        for (int i = 1; i <= N; i++) {
            //当前票据和前面已经可以放入的票据有多少不起冲突
            while (arr[i][0] - arr[left+1][0] >= K) left++;

            for (int j = 0; j <= M; j++) {
                //前面已经可以存在的价值,放入新的以后同样可以存在
                dp[i][j] = dp[i-1][j];

                if (j >= arr[i][1] && dp[left][j - arr[i][1]] == true) {
                    dp[i][j] = true;
                    max = Math.max(max, j);
                }
            }
        }
        pw.println(max);
        pw.flush();
        br.close();
    }
}

你可能感兴趣的:(2023年蓝桥杯31天真题冲刺,蓝桥杯,算法,java)