智力大冲浪&Leopard学霸-优先队列-priority_queue的使用(堆排序)

山再高,往上爬,总能登顶;
路再长,走下去,定能到达。

优先队列 priority_queue的使用

首先介绍以下priority_queue这个东西。
这个东西有三个参数
首先第一个参数就是像普通的stack和queue一样,这是这个本身的一个类型。
第二个是这个东西的继承载体,通常用vector<>
第三个是排序的函数,有greater()换个less()这里的类型是排序成员的类型
举个栗子
智力大冲浪
题目描述

小伟报名参加中央电视台的智力大冲浪节目。本次挑战赛吸引了众多参赛者,主持人为了表彰大家的勇气,先奖励每个参赛者m元。先不要太高兴!因为这些钱还不一定都是你的?!接下来主持人宣布了比赛规则:
首先,比赛时间分为n个时段(n≤500),它又给出了很多小游戏,每个小游戏都必须在规定期限ti前完成(1≤ti≤n)。如果一个游戏没能在规定期限前完成,则要从奖励费m元中扣去一部分钱wi,wi为自然数,不同的游戏扣去的钱是不一样的。当然,每个游戏本身都很简单,保证每个参赛者都能在一个时段内完成,而且都必须从整时段开始。主持人只是想考考每个参赛者如何安排组织自己做游戏的顺序。作为参赛者,小伟很想赢得冠军,当然更想赢取最多的钱!注意:比赛绝对不会让参赛者赔钱!

输入

第1行为m,表示一开始奖励给每位参赛者的钱;
第2行为n,表示有n个小游戏;
第3行有n个数,分别表示游戏1到n的规定完成期限;
第4行有n个数,分别表示游戏1到n不能在规定期限前完成的扣款数。

输出

小伟能赢取最多的钱。

Sample Input

10000
7
4 2 4 3 1 4 6
70 60 50 40 30 20 10

Sample Output

9950

这题是一个贪心思路的题,贪心思路是寻找当前可以满足时间的最优解,意思就是,如果你这个填入不满足的话,就腾出来一个时间给他(排序后时间差一定会控制在1之内)所以就pop这个头顶元素,这样就把这一个时间腾出来了。
AC时间到

#include<unordered_map>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<utility>
#include<stdio.h>
#include<vector>
#include <stack>
#include<string>
#include<math.h>
#include<cmath>
#include<queue>
#include<map>
#pragma warning(disable:4244)
#define PI 3.1415926536
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll ll_inf = 9223372036854775807;
const int int_inf = 2147483647;
const short short_inf = 32767;
const char char_inf = 127;
inline ll read() {
	ll c = getchar(), Nig = 1, x = 0;
	while (!isdigit(c) && c != '-')c = getchar();
	if (c == '-')Nig = -1, c = getchar();
	while (isdigit(c))x = ((x << 1) + (x << 3)) + (c ^ '0'), c = getchar();
	return Nig * x;
}
inline void out(ll a)
{
	if (a < 0)putchar('-'), a = -a;
	if (a >= 10)out(a / 10);
	putchar(a % 10 + '0');
}
ll qpow(ll x, ll n, ll mod) {
	ll res = 1;
	while (n > 0) {
		if (n & 1)res = (res * x) % mod;
		x = (x * x) % mod; n >>= 1;
	}
	return res;
}
#define read read()
struct node {//存储
	ll t, val;
}save[1000000];
bool cmp(node a, node b)//让时间小的放在最前面这样的话入队列时可以控制时间差在1之内
{                       //当前的时间要么等于限定时间,要么在限定时间之后。
	return a.t < b.t;   //那些有可能叠加时间的导致当前去掉一个pop不能满足的
}                       //都会在每一次的pop中去除。因为不可能出现当前的时间会比以用时间小的
int main()
{
	ll tot = read;//记录总共的money
	ll num = read;
	ll sum = 0;
	for (ll i = 0; i < num; i++)save[i].t = read;
	for (ll i = 0; i < num; i++)
	{
		save[i].val = read;
		sum += save[i].val;//记录当前的可扣的所有的money
	}
	sort(save, save + num, cmp);
	priority_queue<ll, vector<ll>, greater<ll>>q;
	for (ll i = 0; i < num; i++)
	{
		q.push(save[i].val);//入队列
		if (q.size() > save[i].t)q.pop();//剔除队列
	}
	while (!q.empty()) {
		sum -= q.top();//减去那些可以不扣的money,剩下的就是必须扣的钱了
		q.pop();
	}
	cout << tot - sum << endl;
	return 0;
}

举例二
Leopard学霸
输入

每门功课都耗费1单位时间来学习,从0时刻开始,有1000000000个单位时间。在任意时刻,都可以任意一门功课(编号1~n)来学习。
对于第i门功课,有一个截止时间Di,若学完这门功课,就能够获得知识Pi。
在给定的功课和截止时间下,能够获得的知识最多为多少呢?

输出

第一行,一个整数n,表示功课的数目
接下来n行,每行两个整数,Di和Pi

Sample Input

3
2 10
1 5
1 7

Sample Output
17

分析
这题思路很清晰,和智力大冲浪一样这个就更直接了直接找可以获得多少value
代码如下
AC时间到

#include<unordered_map>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<utility>
#include<stdio.h>
#include<vector>
#include <stack>
#include<string>
#include<math.h>
#include<cmath>
#include<queue>
#include<map>
#pragma warning(disable:4244)
#define PI 3.1415926536
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll ll_inf = 9223372036854775807;
const int int_inf = 2147483647;
const short short_inf = 32767;
const char char_inf = 127;
inline ll read() {
	ll c = getchar(), Nig = 1, x = 0;
	while (!isdigit(c) && c != '-')c = getchar();
	if (c == '-')Nig = -1, c = getchar();
	while (isdigit(c))x = ((x << 1) + (x << 3)) + (c ^ '0'), c = getchar();
	return Nig * x;
}
inline void out(ll a)
{
	if (a < 0)putchar('-'), a = -a;
	if (a >= 10)out(a / 10);
	putchar(a % 10 + '0');
}
ll qpow(ll x, ll n, ll mod) {
	ll res = 1;
	while (n > 0) {
		if (n & 1)res = (res * x) % mod;
		x = (x * x) % mod; n >>= 1;
	}
	return res;
}
#define read read()
struct node {
	int val, t;
}save[100001];
bool cmp(node a, node b)
{
	return a.t < b.t;
}
int main()
{
	priority_queue<int, vector<int>, greater<int>>q;
	int n = read;
	for (int i = 0; i < n; i++)
	{
		save[i].t = read;
		save[i].val = read;
	}
	sort(save, save + n, cmp);
	for (int i = 0; i < n; i++)
	{
		q.push(save[i].val);
		if (save[i].t < q.size())q.pop();
	}
	ll ans = 0;
	while (!q.empty())
	{
		ans += q.top();
		q.pop();
	}
	cout << ans << endl;
	return 0;
}

By-轮月

发布了32 篇原创文章 · 获赞 11 · 访问量 1180

猜你喜欢

转载自blog.csdn.net/qq_35339563/article/details/104872057