优先队列练习

  1. 你需要驾驶一辆卡车行驶L单位距离。最开始时,卡车上有P单位的汽油。卡车每开1单位距离需要消耗1单位的汽油。如果在途中车上的汽油耗尽,卡车就无法继续前行,因而无法到达终点。在途中一共有N个加油站。第i个加油站在距离起点Ai单位距离的地方,最多可以给卡车加Bi单位汽油。假设卡车的燃料箱的容量是无限大的,无论加多少油都没有问题。那么请问卡车是否能到达终点?如果可以,最少需要加多少次油?如果可以到达终点,输出最少的加油次数,否则输出-1。
    限制条件:1≤N≤10000,1≤L≤1000000,1≤P≤1000000,1≤A<L,1≤B≤100

分析:题目要求我们加油次数最少,那么假定油量为0时再加油,当然这只是理想状况(因为不可能每个加油站都在你油用完的那个位置),不过我们可以这么想“在到达加油站i时,就获得了一次在之后任何时候都可以加Bi油量的权利”。
①首先我们要根据距离对每个加油站排序
②这里我们要使用一个优先队列,在经过加油站i时,往优先队列里加入Bi
③当燃料箱空了时:
i. 如果队列也是空的,则无法到达终点
ii.否则取出优先队列中最大的元素,并用来给卡车加油

/*
25 10 4
21 4
10 10
14 5
20 2
*/
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
int l, p, n;
struct Node {
	int dis;
	int v;
}node[105];
int cmp(Node a, Node b)
{
	return a.dis < b.dis;
}
int main()
{
   cin >> l >> p >> n;
   for (int i = 0; i < n; i++)
   {
		cin >> node[i].dis >> node[i].v;
   }
   //把终点也认为加油站 
   node[n].dis = l, node[n].v = 0;
   n = n + 1;
   sort(node, node + n, cmp);
   priority_queue<int> q;
   int ans = 0, pos = 0, tank = p;
   for (int i = 0; i < n; i++)
   {
		int d = node[i].dis - pos;
		//不断加油直到油量足够行驶到下一个加油站
		while (d > tank)
		{
			if (q.empty())
			{
				puts("-1");
				return 0;
			} 
			tank += q.top();
			q.pop();
			ans++;
		}
		tank -= d;
		pos = node[i].dis;
		q.push(node[i].v);
	} 
	cout << ans << endl;
   	return 0;
} 
  1. 有一个农夫要把一个木板钜成几块给定长度的小木板,每次锯都要收取一定费用,这个费用就是当前锯的这个木版的长度,给定各个要求的小木板的长度,及小木板的个数n,求最小费用。戳这->原题POJ3253
    提示:

    3
    8 8 5为例:
    先从无限长的木板上锯下长度为 21 的木板,花费 21
    再从长度为21的木板上锯下长度为5的木板,花费5
    再从长度为16的木板上锯下长度为8的木板,花费8
    总花费 = 21+5+8 =34
    要使总费用最小,那么每次只选取最小长度的两块木板相加,再把这些和累加到总费用中即可。这里我们用优先队列做。
#include <iostream>
#include <queue>
using namespace std;
int main()
{
	int n;
	cin >> n;
	priority_queue<long long, vector<long long>, greater<long long> > q;
	while (n--)
	{
		long long x; 
		cin >> x;
		q.push(x);
	} 
	long long ans = 0;
	while (q.size() > 1)
	{
		long long m1 = q.top();
		q.pop();
		long long m2 = q.top();
		q.pop();
		ans += m1 + m2;
		q.push(m1 + m2);
	} 
	cout << ans << endl;
	return 0;
}

HDU1509
这题主要是要重载<运算符,默认情况下return a < b,即升序,但是在优先队列中是降序排列。所以我们要这样写:

bool operator < (Node a, Node b)
{
	if (a.priority != b.priority)
	{
		return b.priority < a.priority;
	}
	return b.num < a.num;
}
#include <iostream>
#include <queue>
#include <string>
using namespace std;
struct Node {
	int num, priority, parameter;
	string val;
}node;

bool operator < (Node a, Node b)
{
	if (a.priority != b.priority)
	{
		return b.priority < a.priority;
	}
	return b.num < a.num;
}
int main()
{
	int a, b, k = 0;
	string s;
	priority_queue<Node> q;
	while (cin >> s)
	{
		if (s == "PUT")
		{
			cin >> node.val >> node.parameter >> node.priority;
			node.num = k++;
			q.push(node);
		}
		else
		{
			if (!q.empty())
			{
				node = q.top();
				q.pop();
				cout << node.val << " " << node.parameter << endl;
			}
			else
			{
				cout << "EMPTY QUEUE!" << endl;
			}
		}
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值