贪心,类似霍夫曼编码
每次找出 最短的两个plank合并并加入集合中, 总共需要合并N次,每一次查找最短plank需要O(N)。
参考了别人代码,对时间常数进行优化才能AC(记录位置并不交换)
/*
PROG: Fence Repair
LANG: C++11
*/
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <climits>
#include <ctype.h>
#include <queue>
#include <stack>
#include <vector>
#include <utility>
#include <deque>
#include <set>
#include <map>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <time.h>
using namespace std;
#define mst(a,b) memset(a,b,sizeof(a))
typedef long long ll;
const int N = 100010;
const ll MOD = 1000000007;
const int INF = 0x7fffffff;
ll a[20002];
int main()
{
clock_t t1 = clock();
ll n, m, i, sum;
cin >> n;
sum = 0;
for(i = 0; i < n; i++){
scanf("%lld", &a[i]);
}
clock_t t2 = clock();
int s = 0, temp = 0;
int min1, min2;
while(s+1 < n){
// find two shortest plank
if(a[s] > a[s+1])
swap(a[s], a[s+1]);
min1 = s; min2 = s+1;
for(i = s+2; i < n; i++){ // 记录序号并不交换
if(a[i] < a[min1]){ // 优化了时间常数才AC
min2 = min1;
min1 = i;
}
else if(a[i] < a[min2]){
min2 = i;
}
}
int temp = a[min1] + a[min2];
if(min2 == s)
swap(min1, min2);
a[min1] = a[s];
a[min2] = temp;
sum += temp;
s++;
}
cout << sum << endl;
clock_t t3 = clock();
//cout << "total time : " << (double)(t3-t1)/CLOCKS_PER_SEC << endl;
return 0;
}