要和“合并石子”的动态规划做法区别开!(见https://blog.csdn.net/m0_38033475/article/details/79677970)
区别在于:合并石子是要求“每次只能合并相邻堆”,而此题没有这个要求,所以根据贪心的思想,就是每次都去合并最小的两堆!
那么,每次选两个最小的...依次合并....联想哈夫曼树的构造方法,其实此题是“求哈夫曼树的带权路径和”,其实也就是求“非叶节点值的和”!
AC代码:
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
//构造哈夫曼树,用优先队列模拟小顶堆
#include<queue>
int n;
int main()
{
while(scanf("%d",&n)!=EOF)
{
priority_queue<int, vector<int>, greater<int> >q;
for(int i=1;i<=n;i++)
{
int a;
cin>>a;
q.push(a);
}
//找到最小的两个,合成一个,以此类推直至只剩根节点
int ans=0;
while(q.size()>1)
{
int a=q.top();
q.pop();
int b=q.top();
q.pop();
int c = a+b;
ans+=c;
q.push(c);
}
cout<<ans<<endl;
}
return 0;
}