zoukankan      html  css  js  c++  java
  • [Codevs] 1063 合并果子

    1063 合并果子

    2004年NOIP全国联赛普及组

    时间限制: 1 s
    空间限制: 128000 KB
    题目等级 : 钻石 Diamond
     
    题目描述 Description

    在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。
    每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过n-1次合并之后,就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。
    因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为1,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。
    例如有3种果子,数目依次为1,2,9。可以先将1、2堆合并,新堆数目为3,耗费体力为3。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为12,耗费体力为12。所以多多总共耗费体力=3+12=15。可以证明15为最小的体力耗费值。

    输入描述 Input Description

     输入包括两行,第一行是一个整数n(1<=n<=10000),表示果子的种类数。第二行包含n个整数,用空格分隔,第i个整数ai(1<=ai<=20000)是第i种果子的数目。

     
     
    输出描述 Output Description

    输出包括一行,这一行只包含一个整数,也就是最小的体力耗费值。输入数据保证这个值小于231

     
     
    样例输入 Sample Input

    3
    1 2 9

    样例输出 Sample Output

    15

    数据范围及提示 Data Size & Hint

    对于30%的数据,保证有n<=1000:
    对于50%的数据,保证有n<=5000;
    对于全部的数据,保证有n<=10000。

    分析 Analysis

    第一次看到这道题的时候,当即套上区间DP,瞬间拿到10分,然后全WA。

    = =现在再看原来是堆。

    显然的最佳方案就是每次都拿最小的两堆进行合并。

    代码 Code

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 using namespace std;
     5 
     6 int heap[100000],hs;
     7 
     8 void pushdown(int p){
     9     int x = heap[p];
    10     int q = 2*p;
    11     while(q <= hs){
    12         if(q < hs && heap[q+1] < heap[q])
    13             q++;
    14         if(x <= heap[q])
    15             break;
    16         heap[p] = heap[q];
    17         p = q;
    18         q = p*2;
    19     }
    20     heap[p] = x;
    21 }
    22 
    23 void pushup(int q){
    24     int x = heap[q];
    25     int p = q/2;
    26     while(p && heap[p] > x){
    27         heap[q] = heap[p];
    28         q = p;
    29         p = q/2;
    30     }
    31     heap[q] = x;
    32 }
    33 
    34 void insert(int x){
    35     heap[++hs] = x;
    36     pushup(hs);
    37 }
    38 
    39 int getmin(){
    40     int x = heap[1];
    41     heap[1] = heap[hs--];
    42     pushdown(1);
    43     return x;
    44 }
    45 
    46 int main(){
    47     int n,tmp;
    48     scanf("%d",&n);
    49     
    50     for(int i = 1;i <= n;i++){
    51         scanf("%d",&tmp);
    52         insert(tmp);
    53     }
    54     
    55     int cnt1,cnt2;
    56     int ans = 0;
    57     
    58     while(hs > 1){
    59         cnt1 = getmin();
    60         cnt2 = getmin();
    61         ans += cnt1+cnt2;
    62         insert(cnt1+cnt2);
    63     }
    64     
    65     printf("%d",ans);
    66     
    67     return 0;
    68 }
    推荐不看
    转载请注明出处 -- 如有意见欢迎评论
  • 相关阅读:
    PTA 5-3 树的同构 ——理解递归
    停车管理系统
    两个有序链表序列的合并 (15分)
    lua 面向对象笔记 继承 和 组合
    二叉树高度计算,判定是否为平衡二叉树
    会用git的重要性,记工作中使用git reset 代码丢失的教训
    #include <bits/stdc++.h> 万能头文件
    C++中类的静态变量成员
    C++创建对象加括号和不加括号的区别
    deepin(深度系统)安装微信 qq
  • 原文地址:https://www.cnblogs.com/Chorolop/p/7229937.html
Copyright © 2011-2022 走看看