第十二届国赛真题-巧克力

这篇博客讨论了一道编程题目,涉及到如何利用贪心算法解决在有限种类和保质期内购买巧克力的问题。作者首先介绍了问题背景,然后详细解释了其采用的贪心策略:按价格升序排序巧克力,并从保质期较长的巧克力开始选择。在代码实现部分,作者展示了如何组织数据结构和遍历过程,以确保找到满足条件的最低花费。虽然代码通过了91%的测试用例,但作者也提到了特殊情况可能导致错误答案的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

小蓝很喜欢吃巧克力,他每天都要吃一块巧克力。
一天小蓝到超市想买一些巧克力。超市的货架上有很多种巧克力,每种巧克力有自己的价格、数量和剩余的保质期天数,小蓝只吃没过保质期的巧克力,请问小蓝最少花多少钱能买到让自己吃 x 天的巧克力。

输入

输入的第一行包含两个整数 x, n,分别表示需要吃巧克力的天数和巧克力的种类数。
接下来 n 行描述货架上的巧克力,其中第 i 行包含三个整数 ai, bi, ci,表示第 i 种巧克力的单价为 ai,保质期还剩 bi 天(从现在开始的 bi 天可以吃),数量为 ci。

输出

输出一个整数表示小蓝的最小花费。如果不存在让小蓝吃 x 天的购买方案,输出ࠪ 1。

样例输入复制

10 3
1 6 5
2 7 3
3 10 10

样例输出复制

18

提示

【样例说明】
一种最佳的方案是第 1 种买 5 块,第 2 种买 2 块,第 3 种买 3 块。前 5 天
吃第 1 种,第 6、7 天吃第 2 种,第 8 至 10 天吃第 3 种。
【评测用例规模与约定】
对于 30% 的评测用例,n, x ≤ 1000。
对于所有评测用例,1 ≤ n, x ≤ 100000,1 ≤ ai, bi, ci ≤ 109。

本题思路

这道题,我的基本思路就是贪心,先把数据按照价格升序排序,价格一样按照保质期升序拍,数量无所谓,然后呢就是按照由后向前的顺序在,数组里寻找满足条件的巧克力,如果找到了就标记,然后数量减1,如果遍历一轮都没找到那么就说明不能满足,退出循环输出-1

然后如果保质期没有大于等于n天的直接输出-1

有意思的地方是,要从后向前走,为啥这样呢,因为按照贪心,我们按照价格少的先拿走,但是这个价格低的可能保质期最长,刚刚好必须要在最后一天才能吃,如果我们在第一天就因为价格低吃掉了就会出错,输出-1

下面上代码 过91%

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Arrays;

public class Main巧克力 {

	public static void main(String[] args) throws IOException {
		StreamTokenizer x=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
		PrintWriter out=new PrintWriter(System.out);
		x.nextToken();
		int n=(int)x.nval;
		x.nextToken();
		int m=(int)x.nval;
		Qkl aa[]=new Qkl[m];
		boolean f=true;
		for(int i=0;i<m;i++) {
			int a,b,c;
			x.nextToken();
			a=(int)x.nval;
			x.nextToken();
			b=(int)x.nval;
			x.nextToken();
			c=(int)x.nval;
			aa[i]=new Qkl(a, b, c);
			if(b>=n)
				f=false;
		}
		if(f) {
			out.println(-1);
			out.flush();
			return;
		}
		Arrays.sort(aa);
		long sum=0;
		int beg=0;
		for(int i=n;i>=1;i--) {//从后面开始选,因为可能价格低,时间也长,如果我们先选了便宜的时间长的那么在后面就没法达到最长
			//就是明明有答案但是输出-1;
			f=true;
			for(int j=beg;j<m;j++) {
				if(aa[j].sl>0&&aa[j].sj>=i) {
					sum+=aa[j].jg;
					aa[j].sl--;
					f=false;
					break;
				}
			}
			if(f)
				break;
		}
		if(f)
			out.println(-1);
		else
		    out.println(sum);
		out.flush();
	}

}
class Qkl implements Comparable<Qkl>{
	int jg;
	int sj;
	int sl;
	public Qkl(int jg,int sj,int sl) {
		this.jg=jg;
		this.sj=sj;
		this.sl=sl;
	}
	@Override
	public int compareTo(Qkl o) {
		if(this.jg<o.jg)
			return -1;
		else if(this.jg==o.jg) {
			if(this.sj<o.sj)
				return -1;
			else if(this.sj==o.sj)
				return 0;
			else
				return 1;
		}
		else
			return 1;
		
	}
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值