农夫约翰为了修理栅栏,要将一块很长的木板切割成 N 块,准备切成的木板长度为 Ln ,未切割前木板的长度恰好为切割后木板长度的总和。每次切断木板时,需要的开销为这块木板的长度。例如长度为21的木板要切成长度为 5、8、8 的三块木板,长 21 的木板切成长度为 13 和 8 的木板时 开销为 21 。再将长度为13的板切成长度为 5 和 8 的板时,开销为 13 。于是合计开销为 34 。 请求出按照目标要求将木板切割完的最小开销是多少。
题目中 1 <= N <= 20000 , 0 <= Li <= 50000
输入:第一行是将木板切割成的块数 N ,第二行有 N 个数,分别为第 Li 块木板的长度。
输出:k,木板切割完的最小开销。
sample input:
3
8 5 8
sample output:
34
贪心,其实就算霍夫曼编码的思想,开销越大的越先切
34 = (5+8) *2 + 8 = 34
# include <bits\stdc++.h>
using namespace std;
typedef long long ll;
const int MAX_N = 20010;
int N, L[MAX_N];
void solve()
{
ll ans = 0;
// 直到计算到模板1块为止
while (N > 1)
{
// 求出最短的板和次短的板
int mii1 = 0, mii2 = 1;
if(L[mii1] > L[mii2])
swap(mii1, mii2);
for (int i = 2; i < N; i++)
{
if(L[i] < L[mii1])
{
mii2 = mii1;
mii1 = i;
}
else if(L[i] < L[mii2])
{
mii2 = i;
}
}
// 将两块木板合并
int t = L[mii1] + L[mii2];
ans += t;
if(mii1 == N - 1)
swap(mii1, mii2);
L[mii1] = t;
L[mii2] = L[N - 1];
N--;
}
cout << ans;
}
还可以有更好的方法解决
来源:CSDN
作者:tmhhh
链接:https://blog.csdn.net/weixin_43569916/article/details/104011012