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

news/2024/7/24 2:20:34 标签: 算法, java, 01背包

生活再平凡,也是限量版

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

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

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

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;
    }
}


http://www.niftyadmin.cn/n/148093.html

相关文章

华为OD机试 -找出符合要求的字符串子串(Java) | 机试题+算法思路+考点+代码解析 【2023】

找出符合要求的字符串子串 题目 给定两个字符串,从字符串2中找出字符串1中的所有字符,去重并按照ASCII值从小到大排序 输入字符串1:长度不超过1024 输入字符串2:长度不超过1000000 字符范围满足ASCII编码要求,按照ASCII的值由小到大排序 输入描述: bach bbaaccedfg…

手写promise原理系列二:手写promise的关键逻辑梳理,promise用法原理

文章目录一、如何改变promise的状态&#xff1f;二、一个promise指定多个成功或失败回调&#xff0c;都会调用么&#xff1f;三、改变promise状态和then中的回调函数谁先执行谁后执行&#xff1f;四、promise.then() 返回的 promise 对象的结果由什么决定&#xff1f;五、promi…

初探Java+TestNG自动化测试

最近看到测试组在搭建TestNG框架&#xff0c;周末在家&#xff0c;本地搭建&#xff0c;方便备查。 测试是程序上线的最后一道关&#xff0c;关于测试的三个重要观点。 1&#xff09;测试是为了证明程序有错&#xff0c;而不是证明程序无错误&#xff1b; 2&#xff09;一个好的…

【力扣-SQL】非会员剩余题 刷题知识点总结

之前刷完了SQL入门的十天打卡计划&#xff0c;链接如下&#xff1a;https://leetcode.cn/study-plan/sql/?progressjgmzq5s&#xff0c;刷题知识点总结在&#xff1a;【力扣-SQL入门】10天刷题 知识点总结这篇文章主要记录一下剩下的、非会员的SQL题&#xff08;一共8题&#…

【Unity-c#专题篇】之c#入门篇

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…

QML视图(PathView)

PathView&#xff08;路径视图&#xff09; PathView 显示从内置 QML 类型&#xff08;如 ListModel 和 XmlListModel&#xff09;创建的模型的数据&#xff0c;或者在从 QAbstractListModel 继承的C中定义的自定义模型类。 视图有一个模型&#xff08;定义要显示的数据&…

17_MySQL触发器

在实际开发中&#xff0c;我们经常会遇到这样的情况&#xff1a;有2个或者多个相互关联的表&#xff0c;如商品信息和库存信息分别存放在 2 个不同的数据表中&#xff0c;我们在添加一条新商品记录的时候&#xff0c;为了保证数据的完整性&#xff0c;必须同时在库存表中添加一…

工作流(1):表格设计

我们对工厂流水线的工作流进行设计 比如 &#xff1a;组件装配&#xff0c;拍照-清洗-焊接-下料等 使用mysql数据库&#xff0c;主要工作流相关表有&#xff1a; 一、操作工序(环节、节点)表&#xff1a;work_procedure 所有操作工序(环节、节点)枚举 DROP TABLE IF EXIST…