这题做完后觉得很水,主要的想法就是逆过程思考,原题是截断,可以想成是拼装,一共有n根木棍,最后要拼成一根完整的,每两根小的拼成一根大的,拼成后的木棍长度就是费用,要求费用最少。显然的是一共会拼接n-1次,如果把每根木棍最初的长度想成叶子节点,两个节点的父节点就是这两个节点的长度相加。那么求的就是这n-1个父节点的总和最少。
为实现这个目标,我们使每个父节点的值尽可能的少,由此想到哈夫曼编码的原理。初始条件为一共n根木棍。然后从中选出最短的两根,将这两根拼接成一根,这样得到的父节点的值是最小的。然后将这根木棍放进原来的木棍中,重复该步骤(从木棍堆中选出最短的两根,拼接成一根,放回木棍堆中),进行了n-1次操作后,木棍拼接成了一根完整的,把中间凡是被拼接成的木棍的长度累加起来,即为所求。
其实我并不能证明这种想法一定是正确的,只是感觉很对,结果也AC,我就当它是对的吧。。。
下面是代码,主要用了STL 中的优先队列,push(),pop(),top()函数。
优先队列默认是int型时最大值出来,所以这里要这样定义
priority_queue< int,vector<int>,greater<int> > Q;
这样就是int型时最小值出来。
贴代码:
1 #include <cstdio> 2 #include <queue> 3 using namespace std; 4 5 int main() 6 { 7 int n; 8 scanf("%d",&n); 9 priority_queue< int,vector<int>,greater<int> > Q; 10 for(int i=0; i<n; ++i) 11 { 12 int t; 13 scanf("%d",&t); 14 Q.push(t); 15 } 16 long long int ans =0; 17 for(int i=1;i<n;++i) 18 { 19 int c1,c2; 20 c1 = Q.top(); 21 Q.pop(); 22 c2 = Q.top(); 23 Q.pop(); 24 c1 += c2; 25 Q.push(c1); 26 ans += c1; 27 } 28 printf("%I64d ",ans); 29 return 0; 30 }