蓝桥冲刺31天之白色情人节

生活再平凡,也是限量版

总要热爱着什么,才不会被这无趣的生活吞没

若心有所向,平凡的日子也会泛着光

心怀浪漫宇宙,也珍惜人间日常

A:卡片

题目描述:

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

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

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

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

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

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

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

题解思路:

我们可以通过统计1---X花费每一种卡片的数量去判断是否能拼接X,如果不可以则输出的为X-1,如果可以则继续往下进行拼接

那么怎么样进行卡片使用的统计呢?

我们定义数组count[10] 分别用于表示0---9的使用量

然后每一次对X值每一位数进行判断,当count中有任意一位数超过2021时,结束

参考代码:

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

public class Main {
    public static void main(String[] args) {
        int []count=new int[10];
        for(int i=1;;i++){
          int t=i;
          while(t!=0){//对当前值的每一位数进行判断
            count[t%10]++;
            if(count[t%10]>2021){//出现超过2021张卡片的时候
              System.out.println(i-1);//输出
              return;//强制结束
            }
            t/=10;
          }
        }
    }
}

B:路径

题目描述:

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

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

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

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

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

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

题解思路:

对于点 X,它可以通过 (x-1,x-2,x-3....x-21)获得,那么我们需要到达X点值最小,则对其取min即可,通过数学规律:a,b的最小公倍数=a*b/(a,b的最大公约数),同时,1与任何数的最小公倍数为该数本身,那么我们只需要从22开始到2021,每一次对能到达位置的值取最小即可

参考代码:

import java.io.*;
import java.util.Arrays;
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StreamTokenizer st = new StreamTokenizer(br);
    static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
    public static void main(String[] args) throws Exception {
        int []arr=new int[2022];
        Arrays.fill(arr,1999999999);//直接赋值最大,然后去求最小(经常被骂,但是还是习惯这样写,呜呜呜)
        for (int i=1;i<=22;i++ )arr[i]=i;//从1跳到x,最小公倍数为x,所以1---22的最小公倍数都是本体
        for(int i=22;i<=2021;i++){//从22到2021
            for(int j=1;j<=21;j++){//每一个i都可以从i-21至i-1过去
                arr[i]=Math.min(arr[i],arr[i-j]+jl(i,i-j));//我们选择保留最小
            }
        }
        pw.println(arr[2021]);
        pw.flush();
    }

    public static int nextInt() throws Exception {//int型
        st.nextToken();
        return (int) st.nval;
    }
 
    public static long nextLong() throws Exception {//long型
        st.nextToken();
        return (long) st.nval;
    }
    public static int gcd(int a, int b ) {//求取最大公约数
        return b !=0 ? gcd(b, a%b): a ; 
    }
    
    public static int jl(int a, int b) {//求取最小公倍数
        return a*b/gcd(a,b) ;
    }
}

C:字符统计

题目描述:

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

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

题解思路:

与卡片类似,我们通过数组去存储每一个字符出现的次数,最终选取次数最多的字符,有多个就依次输出

因为A-Z总共有26个字符,所以数组长度至少需要26

通过 charAt(i)-‘A’去对字符转换成0---25,分别对应A---Z,在输出的时候记得转换回来

参考代码:

import java.util.*;

public class Main {
    public static void main(String[] args) {
      Scanner scan = new Scanner(System.in);
      int []arr=new int[27];
      String ss=scan.nextLine();//输入字符串
      int sum=0;//记录最多出现的次数
      for(int i=0;i<ss.length();i++) {
        arr[ss.charAt(i)-'A'+1]++;//对应字符+1(个人采取1---26,也可以用0---25,看习惯)
        sum=Math.max(sum,arr[ss.charAt(i)-'A'+1]);//更改出现最多次数
      }      
      for(int i=0;i<27;i++){
        if(arr[i]==sum)System.out.print((char)(i+'A'-1));//次数==最多次数即输出
      }
    }
  }

D:费用报销

题目描述:

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

为了弥补小明的损失, 公司同意小明用别的票据进行报销, 但是公司财务 要求小明提交的票据中任意两张的日期差不小于 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表示该票据的面值

题解思路:

PS:这题是01背包的变种问题,如果不会01背包的话建议先学01背包,不然看这篇会很头疼

我们可以吧日期统一起来,因为是在同一年内的,比如输入1  10  5,我们就看成10  5;输入是2  10  5,我们就看成(31+10) 5=41 5;这样子可以直接省去月份的干扰,同时方便后续的k值计算

我们通过排序,将日期在前的优先选择放入,后放入的和前面的进行对比差值是否小于k天,同时放入第i张票据时计算能满足的总金额数

最终在第n张票据放完以后,从右往左去找寻能满足的且小于M的最大金额,输出即可

参考代码:

import java.util.*;
import java.io.*;
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StreamTokenizer st = new StreamTokenizer(br);
    static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
    static int []sj ={0,31,28,31,30,31,30,31,31,30,31,30,31};//时间
    static int [][]arr = new int[1010][2];//存放输入
    static boolean [][]pd=new boolean[1010][5010];//判断前i个能组成的m值
    public static void main(String[] args) throws Exception {
        int n=nextInt();
        int m=nextInt();
        int k=nextInt();
        for(int i=1;i<=12;i++) sj[i]+=sj[i-1];
        for(int i=1;i<=n;i++){
            arr[i][0]=sj[nextInt()-1]+nextInt();//存放a月b日对应在一年中的第几天
            arr[i][1]=nextInt();
        }
        Arrays.sort(arr, 1, n + 1, Comparator.comparingInt(a -> a[0]));//排序,按照时间排序
        pd[0][0]=true;
        int l=0;
        for(int i=1;i<=n;i++){//n个商品,把第i个票据选择性放入
            while (arr[i][0] - arr[l + 1][0] >= k) l++;//当前票据和前面已经可以放入的票据有多少不起冲突
            for (int j = 0; j <= m; j++) {
                pd[i][j] = pd[i - 1][j];//前面已经可以存在的价值,放入新的以后同样可以存在
                if (j >= arr[i][1]&&pd[l][j - arr[i][1]]==true) pd[i][j]=true;//01模板样式
            }
        }
        for (int i = m; i >= 0; i--) {
            if (pd[n][i]) {
                pw.println(i);
                pw.flush();
                return;
            }
        }
    }
    public static int nextInt() throws Exception {//int型
        st.nextToken();
        return (int) st.nval;
    }

    public static long nextLong() throws Exception {//long型
        st.nextToken();
        return (long) st.nval;
    }
}

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值