先想出朴素的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;
}
浙公网安备 33010602011771号