來源:
http://ac.jobdu.com/problem.php?pid=1172
題目描述:
哈夫曼樹,第一行輸入一個數n,表示葉結點的個數。需要用這些葉結點生成哈夫曼樹,根據哈夫曼樹的概念,這些結點有權值,即weight,題目需要輸出所有結點的值與權值的乘積之和。
輸入:
輸入有多組數據。
每組第一行輸入一個數n,接着輸入n個葉節點(葉節點權值不超過100,2<=n<=1000)。
輸出:
輸出權值。
樣例輸入:
5
1 2 2 5 9
樣例輸出:
37
方法一:構建Haffman Tree, 然後計算葉節點的權值。
<pre name="code" class="cpp">#include <stdio.h>
#include <algorithm>
using namespace std;
struct Node
{
int e;
Node *lchild, *rchild;
};
bool cmp(Node *a, Node *b)
{
return a->e < b->e;
}
Node *arr[100];
int CreateHaffmanTree(int n)
{
int i=0;
while(i<n-1)
{
Node *root = (Node*)malloc(sizeof(Node));
root->lchild = arr[i];
root->rchild = arr[i+1];
root->e = arr[i]->e + arr[i+1]->e;
arr[++i] = root;
sort(arr+i,arr+n,cmp);
}
return 0;
}
int countHaffmanTree(Node *root, int level)
{
if(root->lchild || root->rchild)
{
return countHaffmanTree(root->lchild, level+1)+
countHaffmanTree(root->rchild, level+1);
}
else return root->e * level;
}
int main()
{
freopen("in.txt", "r", stdin);
int n,e;
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%d",&e);
Node *root = (Node*)malloc(sizeof(Node));
root->e = e;
root->lchild = NULL;
root->rchild = NULL;
arr[i] = root;
}
sort(arr, arr+n, cmp);
CreateHaffmanTree(n);
printf("%d\n",countHaffmanTree(arr[n-1], 0));
return 0;
}
方法二:不建樹,每次吧排序後最小的兩個值加入權值和,將還未統計過的值和新產生的值(最小的兩個數的和)重新排序。
<pre name="code" class="cpp">#include <stdio.h>
#include <algorithm>
using namespace std;
int main()
{
freopen("in.txt","r",stdin);
int n, sum = 0;
int arr[100];
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%d",&arr[i]);
}
sort(arr,arr+n);
i = 0;
while(i<n-1)
{
sum+= arr[i]+arr[i+1];
arr[i+1] = arr[i]+arr[i+1];
i++;
sort(arr+i,arr+n);
}
for(i=0; i<n; i++)
printf("%d ",arr[i]);
printf("%d ",sum);
return 0;
}