zoukankan      html  css  js  c++  java
  • USACO 2009 Open 干草塔 Tower of Hay

    USACO 2009 Open 干草塔 Tower of Hay

    Description

    为了调整电灯亮度,贝西要用干草包堆出一座塔,然后爬到牛棚顶去把灯泡换掉。干草 包会从传送带上运来,共会出现N包干草,第i包干草的宽度是Wi,高度和长度统一为1。干 草塔要从底层开始铺建。贝西会选择最先送来的若干包干草,堆在地上作为第一层,然后再 把紧接着送来的几包干草包放在第二层,再铺建第三层……重复这个过程,一直到所有的干 草全部用完。每层的干草包必须紧靠在一起,不出现缝隙,而且为了建筑稳定,上层干草的 宽度不能超过下层的宽度。按顺序运来的干草包一定要都用上,不能将其中几个干草包弃置 不用。贝西的目标是建一座最高的塔,请你来帮助她完成这个任务吧。

    Input Format

    第一行:单个整数:N,1 ≤ N ≤ 100000 第二行到N + 1行:第i + 1行有一个整数Wi,1 ≤ Wi ≤ 10000

    Output Format

    第一行:单个整数,表示可以建立的最高高度

    Sample Input

    3
    1
    2
    3

    Sample Output

    2

    Hint

    将1 和2放在第一层,将3放在第二层

    Solution

    本题很容易想到从后往前贪心每次只拿到恰好不比上一层小的干草,但这贪心其实是错的。
    如 999 999 1 3这样的数据答案应是3但是贪心得到的是2。

    由于本题阶段性非常明显我们考虑倒着DP。
    对于后i层的干草堆成的塔a对答案的影响有两部分:
    1.塔a最后一层的宽度越短则前面的干草堆成的塔高度更高。
    2.塔a本身的高度。
    DP显然难以同时考虑两部分,我们考虑用贪心合并这两个部分:
    一定存在一种方案使得干草堆成的塔最高的同时最底层也最短。

    所以我们可以用f[i]表示i到n这些干草能堆成的最大高度,g[i]表示最底层的最短宽度。
    f[i]=f[j]+1,g[i]=w[j-1,i] (j>=i,w[j-1,i]>=g[j])

    但是如果直接暴力转移的化时间复杂度是(O(n^2))的不足以胜任这个数据范围。

    观察转移方程可以发现在满足转移条件的情况下,j越大则f[i]、g[i]都更优,故此可以用单调队列优化转移:把j存进队列中,若队头元素的下一位满足转移条件则把队头踢出,每次入队时如果队尾比要入队的元素还要晚满足条件则把队尾删除,每次转移时直接取队头进行转移。

    Code

    #include <cstdio>
    #include <algorithm>
    #define N 100007
    
    int n,s,t,q[N],f[N],g[N],w[N];
    
    int main(){
    	scanf("%d",&n);
    	for (int i=1;i<=n;++i) scanf("%d",&w[i]),w[i]+=w[i-1];
    	q[0]=n+1;
    	for (int i=n;i;--i){
    		while (s<t&&w[q[s+1]-1]-w[i-1]>=g[q[s+1]]) ++s;
    		f[i]=f[q[s]]+1,g[i]=w[q[s]-1]-w[i-1];
    		while (s<=t&&g[q[t]]-g[i]>=w[q[t]-1]-w[i-1]) --t;
    		q[++t]=i;
    	}
    	printf("%d
    ",f[1]);
    	return 0;
    }
    
  • 相关阅读:
    背下来就是电脑高手(转)
    split+ Pattern切割字符串
    java中方法中声明三个点“...”作用
    MRUnit测试
    configuration默认设置
    chmod|chown|chgrp和用法和区别
    hadoop 一些文件操作
    关闭SVN服务
    Hadoop如何计算map数和reduce数
    链式mapreduce
  • 原文地址:https://www.cnblogs.com/hyheng/p/7787530.html
Copyright © 2011-2022 走看看