霍夫曼树之切割木板最小总代价问题
来源:互联网 发布:淘宝店提前收款 编辑:程序博客网 时间:2024/05/17 07:28
对于本题的切割方案,在给出了最终的切割结果后,我们其实可以使用倒推的方法,将最终的小木板不断合成大木板,大木板的长度就是本次合并的开销,和相同条件下的切割的开销是一样的。
这样想的话,想要总开销小的话,其实想想的话,就可以知道,肯定是不断先合并最小的.因为比如一个小木块a合并成大木块b之后大木块b又和别的木块合并成大木块c,那么大木块中的开销其实包含了原先小木块a的两倍长度,并且大木块c继续合并的话,之后合并的木块会包含越来越大倍数的小木板a的长度.
根据这种想法,我们就不断取小木板中最小的两块进行合并,并将合并的大木板放入到其他剩余的小木板中继续取最小的两块进行合并.
源代码如下:
#include<iostream>#include<algorithm>using namespace std;#define Max_N 20000int a[Max_N];int n;int solve1(){int count=n;int ans=0;while(count>1){//cout<<count<<endl; sort(a+n-count,a+n); //对当前剩余的木板进行升序排序 int min1=a[n-count]; int min2=a[n-count+1]; int sum=min1+min2; /* 测试使用 for(int i=0;i<n;i++) { cout<<a[i]<<" "; } cout<<"--------"; cout<<min1<<" "<<min2<<" "<<sum<<endl;*/ ans+=sum; a[n-count+1]=sum; count--;}return ans;}int solve2(){int ans=0;while(n>1){ int min1=0,min2=1; if(a[min1]>a[min2]) swap(min1,min2); for(int i=2;i<n;i++) { if(a[i]<a[min1]) { min2=min1; min1=i; } else if(a[i]<a[min2]) { min2=i; } } int sum=a[min1]+a[min2]; ans+=sum; if(min1==n-1) swap(min1,min2); a[min1]=sum; a[min2]=a[n-1]; n--;}return ans;}int main(){cin>>n;for(int i=0;i<n;i++){cin>>a[i];}cout<<solve2()<<endl;return 0;}solve1函数是我在书上给出的solve2方法的基础上优化的,优化的方面除了代码更加简洁外,此外其复杂度只有O(nlogn),而原先的solve2方法复杂度则有O(n^2).
其实接触过霍夫曼树的同学到这里就可以感觉到本题其实就是个类似于霍夫曼编码的问题。在霍夫曼树中,叶子节点对应的其实就是最终分割的小木板,除了叶子节点之外的节点就是又小木板合并成的大木板。每个大木板的开销其实就是其左右子节点对应的数值之和,进一步变换就是"每个叶子节点与其所处树中深度乘积之和".这里对于霍夫曼树的代价问题就不过多阐述。
PS:现在每天看书上的题目,接触到的题目越来越多,也没太多的时间将每道题写成博客。所以我会每天写两篇博客介绍下当天遇到的个人感觉比较有价值的题目~
0 0
- 霍夫曼树之切割木板最小总代价问题
- VIJOS1456最小总代价
- [vijos1456] 最小总代价
- vijos最小总代价
- vijos1456 最小总代价
- [VIJOS1456]最小总代价
- 最小总代价 状压DP
- 最小代价问题
- 最小代价问题
- 最小代价问题
- [DP]最小代价问题
- 最小代价问题
- 最小代价问题
- 047_木板切割问题(fence repair) poj 3253
- 077_木板切割问题(优先队列)
- 买一送一的最小代价问题
- SSL 1460——最小代价问题
- 最小代价
- 面试题9:菲波那切数列
- IO流_随机获取文本文件中的姓名案例
- C++中的函数重载
- 创建maven项目
- 深度纹理编码网络 (Deep TEN: Texture Encoding Network)
- 霍夫曼树之切割木板最小总代价问题
- 微信小程序使用WebService(Asp.net)进行数据交互
- XML学习总结
- 一道求极值的三角函数题
- Markdown笔记
- Scala基础语法-3Map
- 蓝桥杯试题集ALGO-156(表达式计算)
- 面试题9-题目2:跳台阶
- 数据库事物并发---事物隔离机制