题目链接:http://poj.org/problem?id=3253
题目大意:
农夫Jhon想要把一块木板切成N(1<=N<=20000)块,每块木板长度为Li(1<=Li<=50000),它买了一块长木板,长度刚好是这N个木板长度的总和。他每次切木板时,开销正好是这块木板的长度,例如,一块长度为21的木板想要切成5,8,8,首先将长度为21的木板切成13和8,开销是21,然后将长度为13的木板切成5和8,开销是13,于是总开销是34。问切割出N块木板所需的最小开销是多少。
输入:
行1:整数N
行2-(N+1):单一整数,表示每块木块的长度Li
输出:
行1:切割出N块木板所需的最小开销
分析:
切割木板的情形可以使用二叉树来表示:
总开销就是叶子节点的值和深度的乘机和。
最佳切割方法应该是最短的木块与次短的木块应当是兄弟节点,也就是哈夫曼树。
源码:
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
int N;
int L[20005];
void selectSort(int s)
{
int i;
for(i = s; i < N-1; ++i)
{
if(L[i] > L[i+1])
{
swap(L[i], L[i+1]);
}
else
{
break;
}
}
}
int main() {
int i;
ll sum = 0;
scanf("%d", &N);
for(i = 0; i < N; ++i)
{
scanf("%d", &L[i]);
}
sort(L, L+N);
for(i = 0; i < N-1; ++i)
{
L[i+1] += L[i];
sum += L[i+1];
selectSort(i+1);
}
printf("%lld\n", sum);
return 0;
}