首先我们肯定知道,要想体力最小,那么一定要可重量小的先合并,因此我们肯定要对重量进行排序。那么我们是不是一直要保持这样一个有序的呢?
是的,但是我们合并出新的果子之后,是直接插入原序列中吗?显然太复杂,因此我们想到了用另外一个容器保存。现在我们解决的基本问题,接着是怎么存储。我们知道要使用最小的,所以我们想到了可以在一端出来,另一端进入的数据结构——队列。
q1存储原来的序列,q2存储合并后的果子,合并后的果子重量大体有两种情况:
1.这堆果子必然再次合并
2.这堆果子下次不会合并
所以我们还需要判断合并时使用的是哪个队列中的,然后将新合并的放入q2中
(排序可以直接sort,但是我想练习练习快排)
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int N=1e5+10;
int a[N];
queue<int>q1,q2;
void quick_sort(int l,int r)
{
if(l>=r)return;
int i=l,j=r,x=a[l+r>>1];
while(i<=j)
{
while(x>a[i])i++;
while(x<a[j])j--;
if(i<=j)
{
swap(a[i],a[j]);
i++;
j--;
}
}
quick_sort(l,j);
quick_sort(i,r);
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
quick_sort(1,n);
for(int i=1;i<=n;i++)
{
q1.push(a[i]);
}
int ans=0;
for(int i=1;i<n;i++)//合并n个果子只会合并n-1次
{
int s[3];//因为要选出来2个最小的,所以开了2个空间,但是因为下标舒服,所以取的3
for(int j=1;j<3;j++)
{
if(q2.empty()||(!q1.empty()&&q1.front()<q2.front()))//q2为空表明现在还未合并
{
s[j]=q1.front();
q1.pop();
}
else
{
s[j]=q2.front();
q2.pop();
}
}
ans+=s[1]+s[2];//合并果子消耗的体力加入
q2.push(s[1]+s[2]);//将新合成的果子放入q2中进行下次判断
}
cout<<ans;
return 0;
}