zoukankan      html  css  js  c++  java
  • bzoj 1233: [Usaco2009Open]干草堆tower 【想法题】

    首先这题的$n^3$的DP是比较好想的

    $f[i][j]$表示用前$i$包干草 且最顶层为第$j+1$包到第$i$包 所能达到的最大高度

    然而数据范围还是太大了 因此我们需要去想一想有没有什么单调性

    ----------------------------------------------------------------------------------------------------

    从其他人的题解中 可以看到一个结论 我们尽量使底层最短 便可逐渐达到最优解

    然后再结合递推的思想去做 我们就会使在底层最短的基础上使第二层最短 以此类推……

    然而根据这个结论 我还是没有什么明确的实现思路 不过忽然想到了这样一组数据 

    3

    2 1 4

    我们会发现 仅用前两包 可以达到2的高度 然而加上第3包后 反而只能达到1的高度了

    可是如果倒着推的话 情况就大不一样了 因为多的部分直接堆在底层就好了

    所以倒着推所得到的答案是单调的

    这样的话 我们又可以用 $f[i]$记录以$i$到$n$包做草堆 底层的最小长度 $g[i]$记录此时能达到的最大高度

    这样就优化到$n^2$了

    ----------------------------------------------------------------------------------------------------

    接下来 我们再观察一下递推式

    $f[i]=min(sum[j-1]-sum[i-1])$,$(j>i,f[j]<=sum[j-1]-sum[i-1])$

    显然$f[i]$从较小的j转移过来结果会更优(如果符合转移条件的话)  $(*)$

    而对于转移条件 $f[j]<=sum[j-1]-sum[i-1]$ 我们把式子移项得到 $sum[i-1]<=sum[j-1]-f[j]$

    这样的话 对于决策j 显然$sum[j-1]-f[j]$越大 可以作为决策的情况就越多 而根据$(*)$ 我们知道j越小越好

    因此如果存在决策$k>j$ 满足 $sum[k-i]-f[k]>=sum[j-1]-f[j]$ 那么决策k便一定不能用上

    于是这个问题就转变为了用单调队列来维护单调性DP的经典模型了

    ----------------------------------------------------------------------------------------------------

    具体实现可参考代码(然而如果把上面的内容认真读了还不会自己实现的话……)

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #define rep(i,n) for(int i=1;i<=n;++i)
    #define imax(x,y) (x>y?x:y)
    #define imin(x,y) (x<y?x:y)
    using namespace std;
    const int N=100010;
    int sum[N],f[N],g[N],q[N];
    int n;
    int main()
    {
        scanf("%d",&n);
        rep(i,n)
        {
            scanf("%d",&sum[i]);
            sum[i]+=sum[i-1];
        }
        int ifront=1,itail=1;
        q[1]=n+1;
        for(int i=n;i;--i)
        {
            while(ifront<itail&&sum[q[ifront+1]-1]-sum[i-1]>=f[q[ifront+1]])
            ++ifront;
            f[i]=sum[q[ifront]-1]-sum[i-1];
            g[i]=g[q[ifront]]+1;
            while(ifront<=itail&&sum[q[itail]-1]-f[q[itail]]<=sum[i-1]-f[i])--itail;
            q[++itail]=i;
        }
        printf("%d",g[1]);
        return 0;
    }
  • 相关阅读:
    git
    uniapp
    laravel
    laravel
    js
    js -上传文件获取名字赋值
    laravel
    持续集成
    持续集成
    持续集成
  • 原文地址:https://www.cnblogs.com/sagitta/p/4650681.html
Copyright © 2011-2022 走看看