YY_More

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

先想出朴素的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;
}
posted on 2011-06-24 14:46  YY_More  阅读(206)  评论(0编辑  收藏  举报