蒜头君很想吃果子,正好果园果子熟了。在果园里,蒜头君已经将所有的果子打了下来,按照就近原则把果子合成了 nn 堆。蒜头君决定把所有的果子合成一堆。 因为蒜头君比较懒,为了省力气,蒜头君开始想点子了:
每一次合并,蒜头君可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过 n-1n−1 次合并之后,就只剩下一堆了。蒜头君在合并果子时总共消耗的体力等于每次合并所耗体力之和。
因为还要花大力气把这些果子搬回家,所以蒜头君在合并果子时要尽可能地节省体力。假定每个果子重量都为1,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使蒜头君耗费的体力最少,并输出这个最小的体力耗费值。
例如有 33 堆果子,数目依次为 11,22,99。可以先将 11、22 堆合并,新堆数目为 33,耗费体力为 33。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为 1212,耗费体力为 1212。所以蒜头君总共耗费体力 =3+12=15=3+12=15。可以证明 1515 为最小的体力耗费值。
输入格式
第一行输入一个整数 n(1 \le n \le 10^4)n(1≤n≤104),第二行有 nn 个整数 xx (1 \le x \le 10^4)(1≤x≤104)。
输出格式
输出蒜头君消费的最小体力值。
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
int a[10000];
int n;
void dfs(int x){
int i;
int t;
int q;
q=x;
for(i=q+1;i<=n;i++){
if(a[i]<a[q]){
q=i;
}
}
swap(a[x],a[q]);
}
int main(){
int i;
int sum;
//取反运算
while(~scanf("%d",&n)){
//~是位操作运算符&是与运算,a&=~b即 a= a & (~b)
sum=0;
for(i=1;i<=n;i++)
cin>>a[i];
dfs(1);
dfs(2);
for(i=2;i<=n;i++){
a[i]+=a[i-1];
sum+=a[i];
dfs(i);
dfs(i+1);
}
printf("%d\n",sum);
}
return 0;
}