您的位置:首页 > 其它

uva 10954 add all

2016-03-17 16:26 288 查看
//维护一个堆,即优先权队列,每次取出最小的两个数
#include<iostream>
using namespace std;
const int maxn=5010;
int a[maxn],n;
void sift(int i)	//以i为根的子树调整为堆
{
a[0]=a[i];
int k=i<<1;//计算左儿子指针k
while(k<=n)
{
if(k<n&&a[k]>a[k+1])//计算左右儿子中较小者的下标
k++;
if(a[0]>a[k])//若k位置的值小于子根,则上移到父亲的位置,否则退出循环
{
a[i]=a[k];
i=k;
k=i<<1;
}
else
k=n+1;
}
a[i]=a[0];//将子根值送入腾出的i位置
}
void work()
{
for(int i=n>>1;i;i--)	//建立小根堆
sift(i);
long long ans=0;//结果总和
while(n!=1)
{
swap(a[1],a[n--]);//取出堆首的最小数(与堆尾交换,堆长减1)
sift(1);//重新调整堆
a[1]+=a[n+1];//两个最小数相加,调整堆
ans+=a[1];
sift(1);
}
cout<<ans<<endl;//输出结果
}
int main()
{
while(cin>>n&&n)
{
for(int i=1;i<=n;i++)
cin>>a[i];
work();
}
return 0;
}


STL实现:

#include <iostream>
#include<cstdio>
#include<queue>
using namespace std;
int main()
{
int n,x;
while (~scanf("%d",&n)&&n)
{
priority_queue<int,vector<int>,greater<int> >q;	//	申明从小到大排序的优先权队列
for (int i=0;i<n;i++)
{
scanf("%d",&x);
q.push(x);
}
int ans=0;
for (int i=0;i<n-1;i++)
{
int a=q.top();q.pop();
int b=q.top();q.pop();
ans+=a+b;
q.push(a+b);
}
printf("%d\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: