zoukankan      html  css  js  c++  java
  • CDOJ 204 合并石子

    合并果子

    Time limit
    3000 / 1000 ms (Java / others)
    Memory limit
    65535 / 65535 kb (Java / others)
    Total accepted
    3
    Total submissions
    5

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

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

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

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

    Input

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

    Output

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

    Sample input and output

    Sample InputSample Output
    3 
    1 2 9
    15

    Source

    NOIP2004 提高组
     
     
     
    这道题一开始以为是石子合并的问题写了个动态规划,结果WA了第一个数据,回来查时才突然发现其实算法有问题,动规其实会TLE的。。。。。
    无语后想不出如何解才不会超时,上网查了一下,才发现题意理解错了。。。。。
    原来合并的果子不用是相连的,可以任意合并,于是只需每次合并最小的两堆果子就好了,然后再把合并完的果子堆放入果子堆的数组中,一直循环直到果子堆的数量为1
    重点是如何把果子放入已排序的数组,这里如果使用插入排序时间复杂度是O(n)乘以每次的O(n),时间复杂度变成O(n^2),估计会TLE(不过网上好像有人用插入排序过的。。。),于是想到用最小堆解决
    最小堆建立是O(nlogn),插入是O(logn),删除是O(logn),总时间复杂度是O(nlogn)
    可以AC
    #include <iostream>
    
    using namespace std;
    int dui[10005]={};
    int len=0;
    void exchange(int j,int k)
    {
        int m;
        m=dui[j];dui[j]=dui[k];dui[k]=m;
    }
    void up(int l)
    {
        while (dui[l]<dui[l>>1]){
            exchange(l,l>>1);
            l=l>>1;
        }
    }
    void inside(long s)
    {
        len++;
        dui[len]=s;
        up(len);
    }
    void cut(int g)
    {
        dui[1]=dui[len];
        dui[len]=0;
        len--;
        int j;
        while (g<<1<=len){
            j=g<<1;
            if ((j+1<=len)&&(dui[j+1]<dui[j])) j++;
            if (dui[j]<dui[g]){
                exchange(j,g);
                g=j;
            }else break;
        }
    }
    int main()
    {
        int l,i;
        long s;
        cin>>l;
        for (i=1;i<=l;i++){
            cin>>s;
            inside(s);
        }
        long j=0,k=0,g=0,h=0;
        while (len>1){
            g=dui[1];
            cut(1);
            h=dui[1];
            cut(1);
            j=g+h;
            k=k+j;
            inside(j);
        }
        cout<<k<<endl;
        return 0;
    }

    2014-03-12 13:44:39

  • 相关阅读:
    CF1454F Array Partition
    leetcode1883 准时抵达会议现场的最小跳过休息次数
    leetcode1871 跳跃游戏 VII
    leetcode1872 石子游戏VIII
    CF1355C Count Triangles
    CF1245D Shichikuji and Power Grid
    CF1368C Even Picture
    CF1368D AND, OR and square sum
    CF1395C Boboniu and Bit Operations
    SpringBoot和开发热部署
  • 原文地址:https://www.cnblogs.com/Atlantis67/p/3596185.html
Copyright © 2011-2022 走看看