先想出朴素的DP转移,设f[i,j]为在使用i号机器完成第j工序所需最短时间sum[i,a,b]为i机器从工序a工作到b的时间
f[i,j]=min(f[i',j']+sum[i,j',j]+K)(i'<>i,j-j'<=L)
这样的话时间复杂度是O(N^2*M*L),会死得很惨
怎么办呢?我们发现,N的值是很小的,这就促使我们产生了把每台机器单独考虑的想法
我们现在只考虑计算f[1,j]的情况,那么f[1,j]=min(f[i',j']+sum[1,j',j]+K)=min(f[i',j']-sum[1,1,j'])+sum[1,1,j]+K
括号里的值显然是可以使用单调队列维护的,我们搞N个单调队列,就可以完美的解决这道题了,复杂度是O(N^2*M)
//By YY_More #include<cstdio> const int maxlongint=0x7FFFFFFF; struct node{ int data; int pos; }; int M,N,P,K,S,temp; int L[6],R[6],F[6],sum[6][100010]; node D[6][100010]; void init(){ scanf("%d%d%d%d",&M,&N,&K,&P); for (int i=1;i<=N;i++) for (int j=1;j<=M;j++){ scanf("%d",&S); sum[i][j]=sum[i][j-1]+S; } for (int i=1;i<=N;i++){ L[i]=R[i]=0; D[i][0].data=-K; D[i][0].pos=0; } }; int main(){ init(); for (int i=1;i<=M;i++){ for (int j=1;j<=N;j++){ while (i-D[j][L[j]].pos>P) L[j]++; F[j]=D[j][L[j]].data+sum[j][i]+K; } for (int j=1;j<=N;j++){ temp=maxlongint; for (int w=1;w<=N;w++) if (w!=j) if (temp>F[w]) temp=F[w]; while (L[j]<=R[j]&&D[j][R[j]].data>temp-sum[j][i]) R[j]--; D[j][++R[j]].data=temp-sum[j][i]; D[j][R[j]].pos=i; } } temp=maxlongint; for (int i=1;i<=N;i++) if (temp>F[i]) temp=F[i]; printf("%d",temp); return 0; }