【动态规划11】vijos1243生产产品(dp+单调队列)

来源:互联网 发布:山东二建继续教育网络 编辑:程序博客网 时间:2024/06/05 10:32

题目描述

在经过一段时间的经营后,dd_engi的OI商店不满足于从别的供货商那里购买产品放上货架,而要开始自己生产产品了!产品的生产需要M个步骤,每一个步骤都可以在N台机器中的任何一台完成,但生产的步骤必须严格按顺序执行。由于这N台机器的性能不同,它们完成每一个步骤的所需时间也不同。机器i完成第j个步骤的时间为T[i,j]。把半成品从一台机器上搬到另一台机器上也需要一定的时间K。同时,为了保证安全和产品的质量,每台机器最多只能连续完成产品的L个步骤。也就是说,如果有一台机器连续完成了产品的L个步骤,下一个步骤就必须换一台机器来完成。现在,dd_engi的OI商店有史以来的第一个产品就要开始生产了,那么最短需要多长时间呢?
某日Azuki.7对跃动说:这样的题目太简单,我们把题目的范围改一改
对于菜鸟跃动来说,这是个很困难的问题,他希望你能帮他解决这个问题

输入输出格式

第一行有四个整数M, N, K, L 下面的N行,每行有M个整数。
第I+1行的第J个整数为T[J,I]。
输出只有一行,表示需要的最短时间。

设f[i][j]为生产前i个产品且第i个产品在j机器上生产的最小代价。
那么很容易想到的动态转移方程是f[i][j]=min(f[k][p]+sum[k+1][i][j])其中p!=j且k<i。
sum[i][j][k]表示从第i件到第j件都在k机器上完成的单价和,然而显然可以用前缀和优化,式子再变成
f[i][j]=min(f[k][p]+sum[i][j]-sum[k][j])。这显然是难以维护的。
但是我们发现题目中j的个数很少,那么对于每一个确定的j(假如j==1)的时候,sum[i][j]显然是一个定值,f[i][1]=min(f[k][p]-sum[k][1])+sum[i][1],那么我们需要做的是维护从i-l+1到i区间内f[k][p]-sum[k][1]的最小值。
那么显然可以用单调队列优化。
话说vijos的评测机真是他妈诡异..

#include<bits/stdc++.h>#define fer(i,j,n) for(int i=j;i<=n;i++)#define far(i,j,n) for(int i=j;i>=n;i--)#define ll long longconst int maxn=100010;const int INF=1e9+7;using namespace std;/*----------------------------------------------------------------------------*/inline int read(){    char ls;int x=0,sng=1;    for(;ls<'0'||ls>'9';ls=getchar())if(ls=='-')sng=-1;    for(;ls>='0'&&ls<='9';ls=getchar())x=x*10+ls-'0';    return x*sng;}/*----------------------------------------------------------------------------*/int m,n,cost,l;int T[6][maxn],f[maxn][6],q[6][maxn][2],h[6],t[6],ans=INF;int main(){    scanf("%d%d%d%d",&m,&n,&cost,&l);    fer(i,1,n)        fer(j,1,m){scanf("%d",&T[i][j]);T[i][j]+=T[i][j-1];}    fer(i,1,m)        fer(j,1,n)            f[i][j]=INF;    fer(i,1,n)q[i][t[i]][0]=0;    fer(i,1,m)    {        fer(k,1,n)        {            while(h[k]<=t[k]&&i-q[k][h[k]][0]>l)h[k]++;            int pos=q[k][h[k]][0],s=q[k][h[k]][1];            f[i][k]=min(f[pos][s]-T[k][pos]+T[k][i]+cost,f[i][k]);        }        fer(k,1,n)            fer(j,1,n)                if(k!=j)                {                    while(h[j]<=t[j]&&f[i][k]-T[j][i]<=f[q[j][t[j]][0]][q[j][t[j]][1]]-T[j][q[j][t[j]][0]])t[j]--;                    q[j][++t[j]][0]=i,q[j][t[j]][1]=k;                }    }    fer(i,1,n)    ans=min(ans,f[m][i]);    cout<<ans-cost;}
原创粉丝点击