题目描述
瑞瑞想要亲自修复在他的一个小牧场周围的围栏。他测量栅栏并发现他需要N(1≤N≤20,000)根木板,每根的长度为整数Li(1≤Li≤50,000)。
于是,他神奇地买了一根足够长的木板,长度为所需的N根木板的长度的总和,他决定将这根木板切成所需的N根木板。
(瑞瑞在切割木板时不会产生木屑,不需考虑切割时损耗的长度)瑞瑞切割木板时使用的是一种特殊的方式,
这种方式在将一根长度为x的模板切为两根时,需要消耗x个单位的能量。
瑞瑞拥有无尽的能量,但现在提倡节约能量,所以作为榜样,他决定尽可能节约能量。
显然,总共需要切割N-1次,问题是,每次应该怎么切呢?请编程计算最少需要消耗的能量总和。
输入输出格式
输入格式:
第一行: 整数N,表示所需木板的数量
第2到N+1行: 每行为一个整数,表示一块木板的长度
输出格式:
一个整数,表示最少需要消耗的能量总和
输入输出样例
输入样例#1:
3858
输出样例#1:
34
说明
将长度为21的木板,第一次切割为长度为8和长度为13的,消耗21个单位的能量,
第二次将长度为13的木板切割为长度为5和8的,消耗13个单位的能量,共消耗34个单位的能量,是消耗能量最小的方案。
感觉跟合并果子挺像的吧。
然后就很自然的想到了一种思路,,
一开始答案就等于所有元素的和(肯定的),
在此基础上用贪心的方法继续加。
看着根据样例好像也对,,
就交上了,,,
十分mmp。。
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 using namespace std; 8 9 priority_queue ,greater > 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 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 using namespace std; 8 9 priority_queue ,greater > 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