考虑到每一次切割所花费的代价是所切割的木板的长度,那我们就可以反向思考,合并两块木板所花费的代价是这两块木板的长度和,那么问题就转化为了将输入中给出的N块木板给两两合并在一起。于是,我们会惊奇地发现这道题其实就是合并果子的翻版,一道用小根堆来优化的贪心题!
当然了,手打堆是比较麻烦的,相比之下,C++自带的优先队列就好用多了。代码见下:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#define max(x,y) (x>y?x:y)
#define min(x,y) (x<y?x:y)
#define LL long long
#define N 20000
using namespace std;
int n,a[N+5];
priority_queue<int,vector<int>,greater<int> > q;//建立一个小根堆
int read()//读优
{
int x=0,f=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if(ch=='-') f=-1,ch=getchar();
while(ch>='0'&&ch<='9') (x*=10)+=ch-'0',ch=getchar();
return x*=f;
}
void write(LL x)//输优
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
int main()
{
n=read();
for(int i=1;i<=n;i++) a[i]=read(),q.push(a[i]);//边读入边将数字放入堆中(当然,这题其实完全不需要开数组,可以直接用临时变量来读入)
LL ans=0;//答案要用long long存储
for(int i=1;i<n;i++) {int x=q.top();q.pop(),ans+=(x+=q.top()),q.pop(),q.push(x);}//每次取出堆顶的两个数,将ans加上这两个数之和,并记得将这两个数之和重新放入堆中,
write(ans);
return 0;
}
版权声明:转载请注明地址