题意:
输入n个数将它们相加。相加的时候每次只能选择2个数,然后定义这两个数的和为这一次相加的代价。
问以什么顺序相加可以使得总的代价最小。
思路:
从n个数中选出2个数相加后以后问题就变成了n-1个数相加了,所以我们可以采取的一个贪心策略:每次都选
两个最小的数相加。具体实现的时候可以先对n个数排一下序,然后取前2个数相加,再将结果插入到原数组中(这是插入排序的思想,其实也可以每次都用快排排序,但那样很慢就是了。)。
后面在网上看一下别人的解题报告,发现都说是哈夫曼树的模型,可以采用优先队列解决(哈夫曼树还没看就不管了),然后就写了一个优先队列,果然快了不少。
代码如下:
<span style="font-size:18px;">#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int swap(int &a,int &b)
{
int t;
t=a;
a=b;
b=t;
}
int main()
{
int i,j,n,a[5500];
while(scanf("%d",&n)&&n)
{
for(i=0;i<n;i++)
scanf("%d",&a[i]);
int k=0,cost=0,sum;
sort(a,a+n);
while(k!=n-1)
{
sum=a[k]+a[k+1];
cost+=sum;
++k;
a[k]=sum;
for(i=k;i<n-1;i++)
{
if(a[i]>a[i+1])
swap(a[i],a[i+1]);
else
break;
}
}
printf("%d\n",cost);
}
return 0;
}
</span>
优先队列的:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int main()
{
int i,j,n;
///声明一个小整数优先的优先队列
priority_queue<int,vector<int>,greater<int> >q;
while(scanf("%d",&n)&&n)
{
for(i=0;i<n;i++)
{
int x;
scanf("%d",&x);
q.push(x);
}
int cost=0;
while(n-1)
{
int a=q.top();
q.pop();
int b=q.top();
q.pop();
cost=cost+a+b;
q.push(a+b);
n--;
}
q.pop();
printf("%d\n",cost);
}
return 0;
}