P3045 [USACO12FEB]牛券Cow Coupons 贪心+优先队列

20 篇文章 0 订阅
3 篇文章 0 订阅

题目链接

贪心思路:

0.贪心撤回

1.首先如果所有的奶牛都使用了优惠券,那么优惠价格最少的前K个奶牛是必定包含在最终答案中的。如果情况不是这样,就意味着有一张优惠券用在了K+1到N区间的奶牛上,但是前K个奶牛中的那一个不选,显然这是不划算的,情况不是最优。

2.考虑全部对排序后的前K个奶牛使用优惠券,再建立一个由小到大保存(P[i]-C[i]) 的堆维护,再对[K+1,N]个奶牛进行选择时,比较 堆首 <  P[i]-C[i],意思是使得优惠幅度最大,进行更新,然后对这个加上堆首差价,意思是将这张优惠券对第i个奶牛使用。

同时要对[k+1,n]元素进行原始价格排序。

#include <queue>
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>

using namespace std;

const int MAXN = 50001;
const int INF = 0X3F3F3F3F;

#define lint long long


lint N,K,M;

struct _Cow
{
	int Price;
	int AfterPrice;
}Cow[MAXN];

priority_queue<lint,vector<lint>,greater<lint> > Queue1;

lint ans = 0;

bool cmp1(_Cow a,_Cow b)
{
	return a.AfterPrice < b.AfterPrice;
}

bool cmp2(_Cow a,_Cow b)
{
	return a.Price < b.Price;
}

void Solve(void)
{
	sort(Cow+1,Cow+1+N,cmp1);
	
	lint Sum = 0;
	for(int i = 1;i <= K;i++)
	{
		Sum += Cow[i].AfterPrice;
		if(Sum > M)
		{
			ans = i-1;
			return;
		}
		if(i == N)
		{
			ans = N;
			return;
		}
		Queue1.push(Cow[i].Price-Cow[i].AfterPrice);
	}
	
	sort(Cow+1+K,Cow+1+N,cmp2);
	ans = K;
	for(int i = K+1;i <= N;i++)
	{
		lint MinOff = Queue1.top();
		
		if(MinOff < Cow[i].Price-Cow[i].AfterPrice && !Queue1.empty())    //注意优先队列是否为空
		{
			Sum += MinOff;
			Sum += Cow[i].AfterPrice;
			Queue1.pop();
			Queue1.push(Cow[i].Price-Cow[i].AfterPrice);
		}
		else
		{
			Sum += Cow[i].Price;
		}
		if(Sum > M)
		{
			return;
		}
		ans++;
	}
	return;
};

int main(void)
{
	cin >> N >> K >> M;
	for(int i = 1;i <= N;i++)
	{
		cin >> Cow[i].Price >> Cow[i].AfterPrice;
	}
	
	Solve();
	cout << ans << endl;
	
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值