蓝桥杯 2021国赛 :巧克力

蓝桥杯 2021国赛 :巧克力

贪心,模拟

运行限制
  • 最大运行时间:1s
  • 最大运行内存: 256M

题目描述

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

输入描述

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

输出描述

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

样例

输入
10 3
1 6 5
2 7 3
输出
18

样例说明

一种最佳的方案是第 1 种买 5 块,第 2 种买 2 块,第 3 种买 3 块。前 5 天吃第 1 种,第 6、7 天吃第 2 种,第 8 至 10 天吃第 3 种。

评测用例规模与约定

对于 30% 的评测用例,n, x \le 1000 n,x≤1000;

对于所有评测用例,1 ≤ \leq n, x ≤ \leq 100000,1 ≤ \leq ai, bi, ci ≤ \leq 1 0 9 10^9 109

思路

这题是一道贪心问题,即要贪花费,也要贪时间。
这题我们按照时间从后往前贪,即先把数据按照保质期的大小,从大到小排序,然后再使用优先队列,把保质期大于等于当前日期的所有商品的最经济的商品找出。购买它,为了方便计算是不是要购买更多,我们只要购买一个,然后判断这个商品还有没有,如果购买了一个后,这个商品还有,我们再把这个商品放入优先队列里,在买一次。我们可以通过这样一次只买一包的形式 ,代替一次买好多包的情况。

关于按价格实惠的先买的话,我们不能确定,能不能买到第 n n n 天的巧克力
例如以下数据:

10 3
1 10 3
2 5 5
3 7 10

如果按时间从前往后,实惠的先买的话,就会出现下面这种情况

天数:  1 2 3 4 5 6 7 8 9 10
价格:  1 1 1 2 2 3 3          //当天吃的巧克力的价格

而正确的吃法应该是下面这样的

天数:  10 9 8 7 6 5 4 3 2 1     //第几天
价格:  1  1 1 3 3 2 2 2 2 2

代码

#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int N =1e5+10;

struct node
{
    int a,b,c;
    bool operator < (const node &w)const
    {
    	//操作符重载
    	//让优先队列里的数据按价格由小到大排序
        return a>w.a;
    }
};
node q[N];
int cmp(node &cc,node &e)
{
	//sort 排序规则
	//让数据按保质期由大到小排序
  	return cc.b>e.b;
}

int n,x; 

int main()
{    
    cin>>x>>n;
    for(int i = 0 ; i < n ; i ++)
    {
        int a,b,c;
        cin>>q[i].a>>q[i].b>>q[i].c;
    }
    sort(q,q+n,cmp);
    priority_queue<node> hh;
    
    long long sum=0;  //价格总和是 n*a = 1e5 * 1e9 = 1e14 会爆int 
    int now_date = x; //现在买到第几天的巧克力
    int cnt = 0 ;
    
    hh.push(q[cnt++]);
    
    while(!hh.empty()&&now_date>0)
    {
        while(q[cnt].b>=now_date && cnt < n)
        {
            hh.push(q[cnt++]);
        }
        node t = hh.top();
        hh.pop();
        
        sum+=t.a;
        now_date--;
        t.c--;
        if(t.c>0) hh.push(t);
    }
    if(now_date>0) puts("-1");
    else printf("%lld\n",sum);
    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值