背景:一个农场主要修篱笆,需要N段木头(1<= N <= 1000),每段木头长度不同( 1<= L <= 50000)。现在他有一颗长度恰好合适的树干,去找人锯成N段。每锯一次收费为当前长度总和。
例如: 需要3段木头,每段长为8、 5 、8 。第一次据的时候总长度为8+5+8 = 21,收费21 ,假设锯为8 和13 两段,再将13那一段剧为5和8,收费13。总收费为34
问题:求该农场主锯完木头的最低收费是多少。
分析:
这个题,反过来想,N段木头的数组,每次找两个最小的段数组,组合后放入原队列,继续组合。其实就是哈夫曼树。但是我想不出怎么证明。
编程需要一个最小优先队列,以每次从队列中取出最小的两个数,把组合的新数入队。我使用最小堆实现的。代码如下:
#include <iostream>
using namespace std;
//鍫嗕繚鎸侊紝arr[0]涓哄爢闀垮害銆?
void Minheapify( int * arr , int i)
{
if(arr == NULL || arr[0] <= 0 || arr[0] < i )
{
return;
}
int left = 2*i;
int right = 2*i + 1;
int minIndex = i;
if( left <= arr[0] && arr[left] < arr[minIndex] )
{
minIndex = left;
}
if( right <= arr[0] && arr[right] < arr[minIndex] )
{
minIndex = right;
}
if( minIndex != i )
{
int temp = arr[minIndex];
arr[minIndex] = arr[i];
arr[i] = temp;
Minheapify( arr , minIndex );
}
}
void BuildHeap( int * arr )
{
if( arr == NULL || arr[0] <= 0 )
return;
int len = arr[0];
for( int i = len/2 + 1 ; i >0 ; i-- )
{
Minheapify( arr , i );
}
}
int HeapExtractMin( int * arr )
{
if( arr == NULL || arr[0] <= 0 )
return -1;
int min = arr[1];
arr[1] = arr[ arr[0] ];
arr[0] -= 1;
Minheapify( arr , 1 );
return min;
}
void HeapDecreaseKey( int * arr , int i ,int key )
{
if( arr == NULL || arr[0] <= 0 || i > arr[0] )
return;
//涓嶅厑璁稿鍔?
if( key > arr[i] )
return;
arr[i] = key;
while( i > 1 && arr[i/2] > arr[i] )
{
int temp = arr[i/2];
arr[i/2] = arr[i];
arr[i] = temp;
i = i/2;
}
}
void MinHeapInsert( int * arr , int key )
{
if( arr == NULL || arr[0] <= 0 )
return ;
arr[0] += 1;
arr[ arr[0] ] = key + 1;
HeapDecreaseKey( arr , arr[0] , key );
}
void Print( int * arr )
{
if( arr == NULL || arr[0] <= 0 )
return;
for( int i = 1; i <= arr[0] ; i++ )
cout<<arr[i];
cout<<endl;
}
int main()
{
int n = 0;
int arr[1024];
while( cin>>n )
{
arr[0] = n;
for( int i = 1; i <= n; i++ )
cin>>arr[i];
BuildHeap( arr );
int sum = 0;
//Print( arr );
while( arr[0] > 1 )
{
int top1 = HeapExtractMin( arr );
// Print( arr );
int top2 = HeapExtractMin( arr );
// Print( arr);
int newElement = top1 + top2;
sum += newElement;
MinHeapInsert( arr , newElement );
// Print( arr);
}
cout<< sum<<endl;
}
return 0;
}