贪心法
#include <iostream>
#include <algorithm>
using namespace std;
//洛谷P1090 合并果子
int L[10001] = {0};
int main()
{
/*第一行是一个整数 n(1≤n≤10000) ,表示果子的种类数。
**第二行包含 n 个整数,用空格分隔,第 i 个整数(1≤ai≤20000) 是第 i 种果子的数目。*/
int N;
cin >> N;
for(int i = 0;i < N;i++)
{
cin >> L[i];
}
long long ans = 0; //200000000
while(N > 1)
{
int mii1 = 0, mii2 = 1;
if(L[mii1] > L[mii2])
swap(mii1, mii2); //头文件algorithm
//这里的swap是为了确保mii1指向的是最小的
for(int i = 2;i < N;i++)//因为mii1已经指向0 1中最小的,所以i直接从2开始即可
{
if(L[i] < L[mii1])//发现更小的
{
mii2 = mii1;//目前的mii1转移给mii2 以保证mii2指向的是次小的
mii1 = i;//mii1指向最小的
}
else if(L[i] < L[mii2])//虽然比mii大但是比mii2小
{
mii2 = i;//与mii2下标互换以确保mii2指向次小
}
}
//将两块板拼合
int t = L[mii1] + L[mii2]; //合并果子需要的花费 从小向大排列 总花费便会最小
ans += t;//将本次合并花费加入到总花费中去
if(mii1 == N - 1) //如果mii1指向的是最后一块
swap(mii1, mii2);//此时mii2指向最后一块 mii1指向次小的板
L[mii1] = t;//最小板被加和取代
L[mii2] = L[N - 1];//次小板被最后一块取代
N--;//扔掉最后一个 指针前移(但其实扔掉的是目前的最小和次小 通过前面的互换保留了最后一块 并且把新的和放入排序)
}
cout << ans;
return 0;
}
优先队列
#include <iostream>
#include <queue>
using namespace std;
//N [1,20000]
int main()
{
int N, x, a = 0, b = 0;
long long sum = 0;
priority_queue<int, vector<int>, greater<int> >que;
cin >> N;
while(N)
{
N--;
cin >> x;
que.push(x);
}//元素逐个入队
while(que.size() != 1)
{
//cout << "size = " << que.size() << endl;
a = que.top();
//cout << "a = " << a << endl;
que.pop();
b = que.top();
//cout << "b = " << b << endl;
que.pop();
sum += a;
sum += b;
//cout << "sum = " << sum << endl;
que.push(a+b);
//cout << "after size = " << que.size() << endl;
}
cout << sum << endl;
return 0;
}