霍夫曼树之切割木板最小总代价问题

                                                         霍夫曼树之切割木板最小总代价问题_第1张图片

对于本题的切割方案,在给出了最终的切割结果后,我们其实可以使用倒推的方法,将最终的小木板不断合成大木板,大木板的长度就是本次合并的开销,和相同条件下的切割的开销是一样的。

这样想的话,想要总开销小的话,其实想想的话,就可以知道,肯定是不断先合并最小的.因为比如一个小木块a合并成大木块b之后大木块b又和别的木块合并成大木块c,那么大木块中的开销其实包含了原先小木块a的两倍长度,并且大木块c继续合并的话,之后合并的木块会包含越来越大倍数的小木板a的长度.

根据这种想法,我们就不断取小木板中最小的两块进行合并,并将合并的大木板放入到其他剩余的小木板中继续取最小的两块进行合并.

源代码如下:

#include
#include
using namespace std;
#define Max_N 20000
int a[Max_N];
int n;
int solve1()
{
	int count=n;
	int ans=0;
	while(count>1)
	{
		//cout<1)
	{
	   int min1=0,min2=1;
	   if(a[min1]>a[min2]) swap(min1,min2);
	   
	   for(int i=2;i>n;
	for(int i=0;i>a[i];
	}
	cout<
solve1函数是我在书上给出的solve2方法的基础上优化的,优化的方面除了代码更加简洁外,此外其复杂度只有O(nlogn),而原先的solve2方法复杂度则有O(n^2).

其实接触过霍夫曼树的同学到这里就可以感觉到本题其实就是个类似于霍夫曼编码的问题。在霍夫曼树中,叶子节点对应的其实就是最终分割的小木板,除了叶子节点之外的节点就是又小木板合并成的大木板。每个大木板的开销其实就是其左右子节点对应的数值之和,进一步变换就是"每个叶子节点与其所处树中深度乘积之和".这里对于霍夫曼树的代价问题就不过多阐述。


PS:现在每天看书上的题目,接触到的题目越来越多,也没太多的时间将每道题写成博客。所以我会每天写两篇博客介绍下当天遇到的个人感觉比较有价值的题目~

你可能感兴趣的:(算法,挑战程序设计竞赛)