原题链接:蓝桥杯2023年第十四届省赛真题-平均
解题思路:
思路:
首先看到代价最小,就想到一定要把价值大的先放进去(这里面引申出桶的存在,用来装0-9数字出现的个数)
然后怎么接收数据呢,ai和bi是关联数据,不能分开存储,想到二维数组和哈希表。
最后用二维数组接后,因为代价是无序的,不一定就按照输入给的那样排好,一定需要重排(为什么?因为我想让价值大的排在前面,先放进桶里。这样的话,即使后面缺了几个这个数,我也只会花费比较小的代价去改那些多出来的数)
二维数组排序,我一开始用了选择排序,按照bi重排了数组,但非常耗时,不出意外超时了,只过了三个例子。既然这样排不行,我就用Arrays.sort+拉姆达表达式,调用方法排序,非常之好用啊。
5.排好后,怎么计算最小代价呢?我已经让代价较大的数先落尽桶里了,剩下没进的都是这个数字已经满了桶装不下的重复数字而且代价都很小,因为这n个数肯定都得用上,那么我只要将多出来的那几个数的代价求和,把这几个数改掉就好了。
注意事项:
参考代码:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Arrays; import java.util.Scanner; /** * @Author:杨雨彤 * @date:2024/1/17 22:00 */ public class Main { static BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); public static void main(String[] args) throws IOException { int n=Integer.parseInt(br.readLine()); int count=n/10;//每个数字应该出现的次数 long[][]arr=new long[n][2];//接收数字以及其对应的值 for (int i = 0; i <arr.length ; i++) { String[]s=br.readLine().split(" "); arr[i][0]=Long.parseLong(s[0]); arr[i][1]=Long.parseLong(s[1]); } //按照代价从大到小排序 Arrays.sort(arr, (a, b) -> Long.compare(b[1], a[1])); int []cnt=new int[10];//桶,用来装每个数字出现的次数 long mincost=0;//记录最少需要的代价 for (int i = 0; i <n ; i++) { if(cnt[(int)arr[i][0]]<count){ //如果桶中数字的数量小于count,则如果还有就继续装 cnt[(int)arr[i][0]]+=1; }else{ mincost+=arr[i][1];//如果桶中某种数字的数量大于要求的count个,表示一定存在其他数字不够count的情况 //并且溢出的数字的个数和缺少的数字个数一定是相等的,要想改掉溢出的数字变成缺少的数字,一定需要付出相应的代价 } } System.out.println(mincost); } }
0.0分
1 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复