考虑到每一次切割所花费的代价是所切割的木板的长度,那我们就可以反向思考,合并两块木板所花费的代价是这两块木板的长度和,那么问题就转化为了将输入中给出的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; }
版权声明:转载请注明地址