• luogu 1090 合并果子


    合并果子
    题目
    [luogu1090]

    题目描述

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

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

    因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。

    假定每个果子重量都为1,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。

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

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

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

    输入输出样例

    输入 #1 复制
    3
    1 2 9
    输出 #1 复制
    1
    说明/提示
    对于30%的数据,保证有n≤1000:

    对于50%的数据,保证有n≤5000;

    对于全部的数据,保证有n≤10000。

    分析

    决策单调。


    这道题与[luogu1880石子合并]有相似之处

    但是是完全不同的两道题,这道题可以任两堆合并而石子合并只能相邻合并。

    但就是这点区别,使两道题不同

    对于合并果子,可以贪心的每次选最小的两堆,反正合并的次数都是一样的,先合并的后面对答案的贡献会多一点,所以要先合并小的。

    但对于石子合并,因为只能合并相邻的两堆,不能保证是最小的两堆,便不能贪心了,合并的是相邻区间,区间动规会更加适合

    我们回到合并果子,这道题是决策单调,每次的选择:

    1.是原数列中的最小两个数

    2.合并过的最小两个数

    3.一个合并过,一个没合并

    我们用两个队列,一个存没合并过的,一个存合并过的

    现将没合并过的排序

    因为都是从小到大,所以后加入的一定比先加入的大

    保证了两个队列的单调性

    代码

     1 /************************
     2 User:Mandy.H.Y
     3 Language:c++
     4 Problem:luogu1090
     5 Algorithm: 
     6 ************************/
     7 #include<bits/stdc++.h>
     8 
     9 using namespace std;
    10 
    11 const int maxn = 1e4 + 5;
    12 
    13 int n,l1,r1,l2,r2;
    14 long long ans;
    15 long long q[maxn],a[maxn];
    16 
    17 template<class T>inline void read(T &x){
    18     x = 0;bool flag = 0;char ch = getchar();
    19     while(!isdigit(ch)) flag |= ch == '-',ch =  getchar();
    20     while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch =  getchar();
    21     if(flag) x = -x;
    22 }
    23 
    24 template<class T>void putch(const T x){
    25     if(x > 9) putch(x / 10);
    26     putchar(x % 10 | 48);
    27 }
    28 
    29 template<class T>void put(const T x){
    30     if(x < 0) putchar('-'),putch(-x);
    31     else putch(x);
    32 }
    33 
    34 void file(){
    35     freopen("testdata(1).in","r",stdin);
    36 //    freopen("1090.out","r",stdin);
    37 }
    38 
    39 void readdata(){
    40     read(n);
    41     for(int i = 1;i <= n; ++ i){
    42         read(a[i]);
    43     }
    44 }
    45 
    46 void work(){
    47         l1 = 1,r1 = n + 1;
    48     sort(a + 1,a + 1 + n);
    49     l2 = r2 = 0;
    50     for(int i = 1;i < n; ++ i){
    51         long long x1,x2,x3,x4,x = 0;
    52         if(l1 < r1) x1 = a[l1];
    53         else x1 =1e15;
    54         if(l1 < r1-1) x2 = a[l1 + 1];
    55         else x2 = 1e15;
    56         if(l2 < r2) x3 = q[l2];
    57         else x3 =1e15;
    58         if(x3 > x1){
    59             x += x1;l1++;
    60             if(x3 > x2) x+=x2,l1++;
    61             else x += x3,l2++;
    62         }else{
    63             x += x3;l2++;
    64             if(l2 < r2) x4 = q[l2];//这里l2已经++ 
    65             else x4 = 1e15;
    66             if(x4 < x1) x += x4,l2++;
    67             else x += x1,l1++;
    68         }
    69         q[r2++] = x;
    70         ans += x;
    71     }
    72     put(ans);
    73 }
    74 
    75 int main(){
    76 //    file();
    77     readdata();
    78     work();
    79     return 0;
    80 }
    View Code
    非做顽石不可,哪管他敬仰暗唾
  • 相关阅读:
    常见动态规划题目详解
    回溯法常见题目总结
    AWK语法入门
    JavaScript深拷贝—我遇到的应用场景
    git代码版本回退
    Rem实现移动端适配
    Weex了解
    Vue.js入门学习
    今日小结—304状态码,数组去重
    js今日小结—Ajax、前端安全、GET&POST、闭包、HTTPS
  • 原文地址:https://www.cnblogs.com/Mandy-H-Y/p/11419069.html
Copyright © 2020-2023  润新知