哈尔曼编码的算法。实质就是每次两个最小的相邻数相加,直到只剩一个数为止,然后把过程中所有的和加起来,较难处理的点就是每次加完了要保证下次相加的必须是最小的两个数。
在这里因为看见数据量比较小(5000个),因此用的O(n*n)的办法做的,就是每次做完和都找到相应位置将数字插进去,前面的数依次向前移动一位,以此保证整个序列始终有序;本来想用排序做,但想想如果每加一次qsort排一次序的话,复杂度为(n*n*logn),会更加费时。
在这里因为看见数据量比较小(5000个),因此用的O(n*n)的办法做的,就是每次做完和都找到相应位置将数字插进去,前面的数依次向前移动一位,以此保证整个序列始终有序;本来想用排序做,但想想如果每加一次qsort排一次序的话,复杂度为(n*n*logn),会更加费时。
代码如下:
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn = 5002;
int cmp(const void *a, const void *b)
{
return *(int *)a - *(int *)b;
}
int main()
{
#ifdef test
freopen("in.txt", "r", stdin);
#endif
int num;
int a[maxn];
while(scanf("%d", &num), num)
{
long long sum = 0;
for(int i = 0; i < num; i++)
scanf("%d", &a[i]);
qsort(a, num, sizeof(a[0]), cmp);
for(int i = 0; i < num - 1; i++)
{
int ans = a[i] + a[i + 1];
sum += ans;
a[i + 1] = ans;
for(int j = i + 1; j < num; j++)
if(ans < a[j])
{
for(int k = i + 1; k < j - 1; k++) // 找到元素位置将其插入,前面的元素依次向前移一位
a[k] = a[k + 1];
a[j - 1] = ans;
break;
}
else if(j == num - 1)
{
for(int k = i + 1; k < num - 1; k++)
a[k] = a[k + 1];
a[num - 1] = ans;
break;
}
}
printf("%lld\n", sum);
}
return 0;
}