郭老师家有个果园,每年到了秋收的时候都会收获很多不同种类的果子。他决定把所有的果子合成一堆,但由于体力有限,郭老师在每次合并的时候只能将两堆果子合并到一起。假设有 n 堆果子,那么经过 n-1 次合并即可完成任务,且消耗的总体力等于每次合并所消耗的体力之和。
因为郭老师还需要保留体力将果子运回家,所以在合并果子过程中要尽可能地节省体力。假定每个果子重量均为1,并且已知果子的种类数和每种果子的数目,你的任务是设计出合理的合并方案,使郭老师耗费的体力最少。
例如有3种果子,数目依次为1,2,9。合并方案如下:
1. 将1、2合并,得到新堆数目为3,耗费体力为3。
2. 将新堆与第三堆合并,又得到新堆,数目为12,耗费的体力为12。
3. 总共消耗体力为 3 + 12 = 15,可以证明15为最小的体力耗费值。
输入
输入包括两行,第一行是一个整数 n (1<=n<=10000),表示果子的种类数。第二行包含 n 个整数,用空格分隔,第 i 个整数 ai (1<=ai<=10000)是第 i 种果子的数目。
输出
输出包括一行,这一行只包含一个整数,即最小的体力耗费值。输出的最小体力小于231。
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
int last = 0,sum=0,len;
void FindMin(int num[])
{
int x1 = last, x2 = last;
int min = num[last];//定义最小
int min2 = INT_MAX;//定义第二最小
for (int i = last; i <len; i++)
{
if (num[i]<min)
{
min = num[i];
x1 = i;
}
}//获得最小
for (int i = last; i < len; i++)
{
if (num[i] <= min2 && i!= x1)
{
min2 =num[i];
x2 = i;
}
}//获得第二小
num[x2] = min + min2;
sum += num[x2];
if (x2 == last)
num[x1] = num[x2];
else
num[x1] = num[last];
num[last] = 0;
last++;
}
int main()
{
int n;
int num[10005] = { 0 };
scanf("%d", &n);
len = n;
if (len == 1)
{
printf("%d\n", num[0]);
return 0;
}
for (int i = 0; i < n; i++)
scanf("%d", &num[i]);
while (n > 1)
{
FindMin(num);
n--;
}
printf("%d\n", sum);
return 0;
}