贪心算法的总结处理

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解。
核心的处理在于:最优子结构的存在,即部分最优解合起来是整体最优解。
以题目进行分析:
P7095 [yLOI2020] 不离https://www.luogu.com.cn/problem/P7095
PS首先感谢一下写题解的大佬,我一开始是真的不会做,按照它的代码慢慢摸索在,终于会了。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
using namespace std;

#define RG register int
#define ll long long
#define ull unsigned long long
#define int long long
const int maxn = 100010;
struct equipment
{
	int power, spirit, padd, sadd;
	inline bool operator<(const equipment &x) const
	{
		return spirit ^ x.spirit ? spirit > x.spirit : sadd ^ x.sadd ? sadd < x.sadd : padd < x.padd;
	}
} Equip[maxn];
template <class T>
inline void read(T &x)
{
	char c = getchar();
	int w = 0;
	x = 0;
	while (!isdigit(c))
		w |= c == '-', c = getchar();
	while (isdigit(c))
		x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
	if (w)
		x = -x;
}
template <typename T>
inline void print(T x)
{
	if (x > 9)
		print(x / 10);
	putchar(x % 10 | 48);
}
priority_queue<equipment> q;
bool cmp(equipment a, equipment b)
{
	return a.power ^ b.power ? a.power < b.power : a.padd > b.padd;
}
signed main()
{
	int t, number;
	read(t);
	read(number);
	for (register int i = 0; i < number; i++)
	{
		read(Equip[i].power), read(Equip[i].spirit), read(Equip[i].padd), read(Equip[i].sadd);
	}
	sort(Equip, Equip + number, cmp);
	int ans = 0, a = 0;
	for (register int i = 0; i < number; i++)
	{
		if (a < Equip[i].power)
		{
			ans = ans + Equip[i].power - a;
			a = Equip[i].power;
		}
		a = a + Equip[i].padd;
	}
	print(ans);
	putchar(' ');
	int ans2 = 0, b = 0; //最小的穿戴精神要求与此时的精神,此时的力量
	//我想要在ans已经确定的前提下利用优先对列进行做题,如何解决?
	//为什么不把ans设为初值呢?
	for (register int i = 0; i < number; i++)
	{
		if (Equip[i].power <= ans)
			q.push(Equip[i]);
		else
		{
			while (ans < Equip[i].power)
			{
				int padd = q.top().padd, spirit = q.top().spirit, sadd = q.top().sadd;
				q.pop();
				if (b < spirit)
				{
					ans2 = ans2 + spirit - b;
					b = spirit;
				}
				b = b + sadd;
				ans += padd;
			}
			q.push(Equip[i]);
		}
		if (i == number - 1)
		{
			while (!q.empty())
			{
				int spirit = q.top().spirit, sadd = q.top().sadd;
				q.pop();
				if (b < spirit)
				{
					ans2 = ans2 + spirit - b;
					b = spirit;
				}
				b = b + sadd;
			}
		}
	}
	print(ans2);
	system("pause");
	return 0;
}
//终于给我过了,哈哈哈哈哈
//难死我了= =
//掌握到了一些精髓
//贪心算法中优先队列的镶嵌使用,通过sort获得第一限制条件能够得到的结果
//再通过priority_queue实现在第一个限制条件下的第二个限制条件的完成
//拓展一下,如果要求有三个限制条件,又或者n个限制条件呢?
//在完成第二个限制条件后,以第一个,第二个为约束条件进行搜索即可,ok!

这道题目的核心问题,如何在第一个限制条件,即保证初始力量最小的条件下筛选出初始精神最小。
对于这个问题,优先队列是一个非常好的办法,其本身只有logN的复杂度,在内部设立一个相对于筛选环境就行。

例题2:例题没有了。。。
给定一个n,下面有n个数据,每行有a,b,c三个数字,保证a+b+c>=0
求初始的资金c,能遍历完全部的数据。

由于最后的值一定大于0,所以我们只需要通过每个数据的t=min(a,a+b)进行筛选就可以,我们要保证最小的启动资金先被筛选到。

正在施工。。。。。。。。。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值