题目描述
瑞瑞想要亲自修复在他的一个小牧场周围的围栏。他测量栅栏并发现他需要N(1≤N≤20,000)根木板,每根的长度为整数Li(1≤Li≤50,000)。
于是,他神奇地买了一根足够长的木板,长度为所需的N根木板的长度的总和,他决定将这根木板切成所需的N根木板。
(瑞瑞在切割木板时不会产生木屑,不需考虑切割时损耗的长度)瑞瑞切割木板时使用的是一种特殊的方式,
这种方式在将一根长度为x的模板切为两根时,需要消耗x个单位的能量。
瑞瑞拥有无尽的能量,但现在提倡节约能量,所以作为榜样,他决定尽可能节约能量。
显然,总共需要切割N-1次,问题是,每次应该怎么切呢?请编程计算最少需要消耗的能量总和。
输入输出格式
输入格式:
第一行: 整数N,表示所需木板的数量
第2到N+1行: 每行为一个整数,表示一块木板的长度
输出格式:
一个整数,表示最少需要消耗的能量总和
输入输出样例
说明
将长度为21的木板,第一次切割为长度为8和长度为13的,消耗21个单位的能量,
第二次将长度为13的木板切割为长度为5和8的,消耗13个单位的能量,共消耗34个单位的能量,是消耗能量最小的方案。
感觉跟合并果子挺像的吧。
然后就很自然的想到了一种思路,,
一开始答案就等于所有元素的和(肯定的),
在此基础上用贪心的方法继续加。
看着根据样例好像也对,,
就交上了,,,
十分mmp。。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<queue> 7 using namespace std; 8 9 priority_queue<int,vector<int>,greater<int> > q; 10 int n; 11 int a[20002]; 12 long long ans,b; 13 14 int main() 15 { 16 scanf("%d",&n); 17 for(int i=1;i<=n;++i) 18 { 19 scanf("%d",&a[i]); 20 ans+=a[i]; 21 q.push(a[i]); 22 } 23 while(q.size() !=1) 24 { 25 b=q.top() ; 26 q.pop() ; 27 b+=q.top() ; 28 q.pop() ; 29 ans+=b; 30 } 31 printf("%lld",ans); 32 return 0; 33 }
然后可以换一种思路,,
虽然并不怎么清楚原来的思路的问题。
多举几个样例就能知道了。
所以ans一开始不必等于所有元素和,
跟上面思路也差不多,
就是可以在踢走最小的元素之后,
把两个最小的元素和在放入堆中。
就可以了。
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<queue> 7 using namespace std; 8 9 priority_queue<int,vector<int>,greater<int> > q; 10 int n; 11 int a[20002]; 12 long long ans,b; 13 14 int main() 15 { 16 scanf("%d",&n); 17 for(int i=1;i<=n;++i) 18 { 19 scanf("%d",&a[i]); 20 q.push(a[i]); 21 } 22 for(int i=1;i<=n-1;++i) 23 { 24 b=q.top() ; 25 q.pop() ; 26 b+=q.top() ; 27 q.pop() ; 28 ans+=b; 29 q.push(b); 30 } 31 printf("%lld",ans); 32 return 0; 33 }
如果你不开心,那我就把右边这个帅傻子分享给你吧,
你看,他这么好看,跟个zz一样看着你,你还伤心吗?
真的!这照片盯上他五秒钟就想笑了。
一切都会过去的。
时间时间会给你答案2333