合并果子 (codevs 1063) 题解

这篇博客介绍了如何解决codevs 1063题——合并果子,以最小化多多合并果子时的体力消耗。文章通过两种方法进行讲解,包括贪心策略结合最小堆以及使用双排序队列。给出了样例输入、输出,以及对应的解题思路和代码实现。
摘要由CSDN通过智能技术生成
【问题描述】

    在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。


    每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过n-1次合并之后,就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。


    因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为1,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。


    例如有3种果子,数目依次为1,2,9。可以先将1、2堆合并,新堆数目为3,耗费体力为3。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为12,耗费体力为12。所以多多总共耗费体力=3+12=15。可以证明15为最小的体力耗费值。

【样例输入】

     3 
    1 2 9

【样例输出】

    15

【解题思路】

     本题为NOIP2004提高组第二题,有两种方法可以解答。一个是贪心+堆,另一个是双排序队列。

     先来说说贪心+堆。

     首先,建一个小根堆,这样就保证根为最小的,取出根并维护小根堆,再取出根并维护小根堆,这样就得到了我们需要的结果,把结果插入堆中并维护,反复这个操作n-1次即可。详见代码。

    然后是队列。

    首先将果子排序,构成一个序列,将最前面的两堆果子取出,放入另一个队列,接下来,就只要判断之后应该取哪两堆,要么取最先的队列中的前两个,要么取新的队列中的前两个,要么取两个队列最前面的一个,然后再放到新的队列中,这样就能保证新的队列必是一个排序好的队列。将新的队列中的每个数加起来便是结果。

【代码实现】

 1 var a:array[0..10000] of longint;
 2     i,n,k,ans,n1:longint;
 3 procedure swap(var a,b:longint);
 4 var y:longint;
 5 begin
 6  y:=a;a:=b;b:=y;
 7 end;
 8 procedure sift(i,m:longint);
 9 var k:longint;
10 begin
11  a[0]:=a[i];
12  k:=2*i;
13  while k<=m do
14   begin
15    if (k<m)and(a[k]<a[k+1]) then
16     inc(k);
17    if a[0]<a[k] then
18     begin
19      a[i]:=a[k];
20      i:=k;
21      k:=i*2;
22     end
23    else
24     k:=m+1</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值