通过一道题 来理解优先队列的使用

74 阅读1分钟

饭堂打饭

由于学校保安收外卖,校花小红很是苦恼,平日里足不出户的她不想去饭堂打饭。于是她想找个帮自己跑腿取饭堂打饭的。这时小红的舍友看到小红想找跑腿,纷纷也想请小红帮忙一起找。于是小红请学校表白墙发布了跑腿招募令。届时小张看到了。一向爱慕小红的小张终于找到了表现自己的机会,于是小张自告奋勇接下了这项活儿。

现已知小红宿舍一共N个人,她们都想吃不同类型的套餐,每种套餐的重量也不一样。如果小张要想一次性把这些饭送到小红宿舍,那么他需要分别把这些不同的套餐给打包到一个大袋子里。小张每一次打包,小张可以把已经打包好的两堆套餐给合并成一堆新套餐,这样花费的时间将会是两堆套餐的重量之和。

为了不想让校花小红等待太久,小张想利用自己学过的编程知识来设计一套花费时间最短的合并方法。

Input

第一行为一个整数N(1<=N<=10000)。 第二行为N个整数,用空格分开,第i个整数ai(1<=ai<=20000)为第i个人想吃套餐的重量。

Output

一个整数,表示小张所需要的最短打包时间。

Sample Input 1

4
7 8 4 2

Sample Output 1

40

可以使用动态规划,但是优先队列的代码更容易实现, 主要核心的思想就是按优先级排列 满足条件的先出

#include<bits/stdc++.h>
using namespace std;
priority_queue <int,vector<int>,greater<int> > q;

int main()
{
	int n,sum,a,b,x,t;
	cin>>n;
	for(int i=0;i<n;i++)	
	{
		cin>>x;
		q.push(x);
	}
	n--;//每次2合1 最后一次直接合一即可 所以总数减1 
	while(n--)
	{
		a = q.top();
		q.pop();
		b = q.top();
		q.pop();
		sum+=a+b;
		t = a+b;
		q.push(t);
	}
	cout<<sum;
return 0;
}