【问题描述】

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

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

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

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

【样例输入】


    1 2 9

【样例输出】

15

【解题思路】

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

先来说说贪心+堆。

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

然后是队列。

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

【代码实现】

 var a:array[..] of longint;
i,n,k,ans,n1:longint;
procedure swap(var a,b:longint);
var y:longint;
begin
y:=a;a:=b;b:=y;
end;
procedure sift(i,m:longint);
var k:longint;
begin
a[]:=a[i];
k:=*i;
while k<=m do
begin
if (k<m)and(a[k]<a[k+]) then
inc(k);
if a[]<a[k] then
begin
a[i]:=a[k];
i:=k;
k:=i*;
end
else
k:=m+;
end;
a[i]:=a[];
end;
procedure heapsort;
var j:longint;
begin
for j:=n div downto do
sift(j,n);
for j:=n downto do
begin
swap(a[],a[j]);
sift(,j-);
end;
end;
function deletemin:longint;
var i,pos:longint;
begin
i:=;
deletemin:=a[];
a[]:=a[n1];
dec(n1);
while *i<=n1 do
begin
pos:=*i;
if (pos<n1)and(a[pos+]<a[pos]) then
inc(pos);
if a[i]>a[pos] then
begin
swap(a[i],a[pos]);
i:=pos;
end
else
break;
end;
end;
procedure insert(k:longint);
var i:longint;
begin
inc(n1);
a[n1]:=k;
i:=n1;
while (i div >)and(a[i div ]>k) do
begin
swap(a[i],a[i div ]);
i:=i div ;
end;
end;
begin
readln(n);
for i:= to n do
read(a[i]);
heapsort;
n1:=n;
for i:= to n- do
begin
k:=deletemin;
k:=k+deletemin;//取出根并维护
ans:=ans+k;
insert(k);//插入结果并维护
end;
writeln(ans);
end.
 var old,new:array[..] of longint;
i,n,fo,fn,rn,ans:longint;
procedure swap(var i,j:longint);
var y:longint;
begin
y:=i;i:=j;j:=y;
end;
procedure sift(i,m:longint);
var k:longint;
begin
old[]:=old[i];
k:=*i;
while k<=m do
begin
if (k<m)and(old[k]<old[k+]) then
inc(k);
if old[]<old[k] then
begin
old[i]:=old[k];
i:=k;
k:=*i;
end
else
k:=m+;
end;
old[i]:=old[];
end;
procedure heapsort;
var j:longint;
begin
for j:=n div downto do
sift(j,n);
for j:=n downto do
begin
swap(old[],old[j]);
sift(,j-);
end;
end;
begin
readln(n);
for i:= to n do
read(old[i]);
heapsort;//这个排序可以是堆排,二叉排序树,快排等等,因为我今天复习到堆,就用堆排了
fo:=;
new[]:=old[]+old[];
ans:=new[];
fn:=;
rn:=;
repeat
if (old[fo+]<>)and(old[fo+]<new[fn])then
begin
inc(rn);
new[rn]:=old[fo]+old[fo+];
ans:=ans+new[rn];
inc(fo,);
end
else
if (new[fn+]<>)and(new[fn+]<old[fo]) then
begin
inc(rn);
new[rn]:=new[fn]+new[fn+];
ans:=ans+new[rn];
inc(fn,);
end
else
if (old[fo]=)and(new[fn+]<>) then
begin
inc(rn);
new[rn]:=new[fn]+new[fn+];
ans:=ans+new[rn];
inc(fn,);
end
else
begin
inc(rn);
new[rn]:=new[fn]+old[fo];
ans:=ans+new[rn];
inc(fo);
inc(fn);
end;
until (old[fo+]=)and(new[fn+]=);
writeln(ans);
end.

合并果子 (codevs 1063) 题解的更多相关文章

  1. T1063 合并果子 codevs

    http://codevs.cn/problem/1063/  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond   题目描述 Description 在一个 ...

  2. codevs 1063 合并果子 STL 优先队列

    1063 合并果子 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://codevs.cn/problem/1063/ Description 在一 ...

  3. codevs 1063 合并果子//优先队列

    1063 合并果子 2004年NOIP全国联赛普及组  时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石    题目描述 Description 在一个果园里,多多已经将所有的果 ...

  4. Codevs 1063 合并果子

    时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond     题目描述 Description 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分 ...

  5. NOIP提高组2004 合并果子题解

    NOIP提高组2004 合并果子题解 描述:在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消 ...

  6. 1063 合并果子 2004年NOIP全国联赛普及组

    题目描述 Description 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消耗的体力等 ...

  7. [KOJ6024]合并果子·改(强化版)

    [COJ6024]合并果子·改(强化版) 试题描述 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多把这些果子堆排成一排,然后所有的果子合成一堆.    每一次合并 ...

  8. [KOJ6023]合并果子·改

    [COJ6023]合并果子·改 试题描述 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多把这些果子堆排成一排,然后所有的果子合成一堆.    每一次合并,多多可以 ...

  9. [KOJ0574NOIP200406合并果子]

    [COJ0574NOIP200406合并果子] 试题描述 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆.    每一次合并,多多可以把两 ...

随机推荐

  1. String相关操作

    1.求字符串中连续出现最多的字串 pair<string, int> substring(const string& str) { ; string substr; vector& ...

  2. onmousemove和onmouseout事件的调用,和js使用双引号、单引号的时候应该注意的问题

    使用js的时候,统一使用双引号,然后通过反斜杠进行转义 ①如果同时使用单引号.和双引号的情况下容易出现问题,导致标签中表示的事件不能调用, ②导致由于标签没有封口而出现样式布局错误 <!DOCT ...

  3. MXNet官网案例分析--Train MLP on MNIST

    本文是MXNet的官网案例: Train MLP on MNIST. MXNet所有的模块如下图所示: 第一步: 准备数据 从下面程序可以看出,MXNet里面的数据是一个4维NDArray. impo ...

  4. only one is important

    今天早上还是去了图书馆,看了一早上的hello world(intel opencl),清楚了程序编写的基本流程,但是,仍和以前一样,貌似看懂了,其实什么也不会,没有发现什么问题.中午,回来取了我的笔 ...

  5. powerdesigner中怎么给一主键设为自增型auto increme

    在使用powerdesigner 设计数据库表时,通常要对主键进行设置,如果主键是int 类型,一般会设置成自增,那么怎么在 powerdesigner 中设置呢,以下是具体的方法: 在所要设为自增型 ...

  6. MySQL:MySQL和SQL Server的区别

    导读:接下来的网上商城的项目,需要用到MySQL数据库了.这个对于我来说,是一个新接触的东西,按照惯例,在刚开始学习一个东西的时候,先从宏观上去了解它.本篇博客,先介绍SQL Server的基本内容, ...

  7. WWF3追踪功能<WWF第六篇>

    WWF工作流提供了Tracking跟踪功能来对工作流实例及其所包含的活动在运行时的状态进行跟踪,以便用户在需要时可以通过这些历史信息进行分析.WWF的Tracking跟踪功能是通过"SqlT ...

  8. Loadrunner:集合点(Rendezvous)

    集合点:等到特定的用户数后再一起执行某个操作,比如一起登录.一起发信,一般情况下使用不到集合点,不过,订票系统或者促销类需要用到,比如说某个促销品的促销时间在8点到8点30,这样的话,就可能出现在8点 ...

  9. windows installer 出错问题解决

    在卸载程序的额时候,如果出现windows installer出错,可以通过一个Windows Installer CleanUp Utility, 有了Windows Installer Clean ...

  10. 添加 SecondaryNameNode

    网络上的很多人写的过程都是错的,关键配置反而不写. SecondaryNameNode的启动有两种方式 一:在整个hdfs系统启动时,在namenode上执行start-dfs.sh则namenode ...