zoukankan      html  css  js  c++  java
  • vijos 1243 生产产品

    貌似两年前联赛复习的时候就看过这题 然而当时大概看看了 感觉太难 便没有去做

    如今再去做的时候 发现其实也并不容易 

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

    这题首先是要处理一下不能在同一台机器上工作L个步骤

    对于这一点 我们可以构造两个数组

    $f[i][j]$表示在第$i$台机器上完成了第$j$个步骤

    $g[i][j]$表示在第$i$台机器上完成了第$j$个步骤 且第$j-1$个步骤不是在第$i$台机器上完成的

    这一个问题解决后 我们通过此题$tag$的提示 会思考一下这题有什么单调性

    我们记$sum[i][j]$表示在第$i$台机器上一直工作完第$j$个步骤所耗费时间(不考虑$L$的限制)

    对于$f[i][j],f[i][p](p<j)$这两个状态

    很明显可以观察出 如果$f[i][p]+(sum[i][j]-sum[i][p])>f[i][j]$

    那么从$p$到$j$一定通过换机器达到了更少的时间消耗

    将上式移项后可将$f[i][p]-sum[i][p]$作为单调队列中元素大小

    每次加入$f[i][j]-sum[i][j]$进行比较

    具体实现细节比较多 可以参考代码

    #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 M=100010;
    int sum[6][M],f[6][M],g[6][M];
    int q[6][M],ifront[6],itail[6];
    int m,n,k,l,ans=2147483647;
    int main()
    {
        scanf("%d%d%d%d",&m,&n,&k,&l);
        int x;
        rep(i,n)
        {
            rep(j,m)
            {
                scanf("%d",&x);
                sum[i][j]=sum[i][j-1]+x;
            }
        }
        memset(f,127,sizeof(f));
        memset(g,127,sizeof(g));
        rep(i,n)
        {
            f[i][1]=g[i][1]=sum[i][1];
            q[i][1]=1;
            ifront[i]=itail[i]=1;
        }
        for(int j=2;j<=m;++j)
        {
            rep(i,n)
            {
                rep(p,5)if(p!=i)
                    g[i][j]=imin(g[i][j],f[p][j-1]+(sum[i][j]-sum[i][j-1]+k));
                while(itail[i]>=ifront[i]&&
                      g[i][q[i][itail[i]]]-sum[i][q[i][itail[i]]]>g[i][j]-sum[i][j])
                        --itail[i];
                q[i][++itail[i]]=j;
                if(q[i][ifront[i]]+l-1<j)++ifront[i];
                f[i][j]=imin(f[i][j],g[i][q[i][ifront[i]]]+(sum[i][j]-sum[i][q[i][ifront[i]]]));
            }
        }
        rep(i,n)
        ans=imin(ans,f[i][m]);
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    哈希表(hash)
    并查集
    trie树(字典树)
    单调队列(滑动窗口)
    单调栈
    用数组实现栈与队列
    数组实现双链表
    数组实现单链表
    区间合并
    离散化
  • 原文地址:https://www.cnblogs.com/sagitta/p/4617474.html
Copyright © 2011-2022 走看看