求助,单调队列优化做法的一个问题
查看原帖
求助,单调队列优化做法的一个问题
1070457
NoneCoding楼主2024/3/5 04:38

对本题单调队列做法熟悉dalao的帮忙解答一下。

看了题解,基本都是用两个队列,第一个队列存“下标”,第二个队列存对应的最优值。但其实第二个队列中的值也是通过第一个队列中存在“下标”计算得到的,两个队列元素是一一对应的。那只用第一个队列应该是可以的,但是我用两个队列就可以AC,只用一个就有问题。自己调了很久没理解,dalao帮忙看看,谢谢。

首先是用两个队列的AC代码

#include <bits/stdc++.h>
using namespace std;

int n,W;
int v,w,m;
int f[40005];
int Que[40005],Que2[40005];

int main(){
	scanf("%d %d",&n,&W);
	for(int i=1;i<=n;i++){	//枚举每个物品
		scanf("%d %d %d",&v,&w,&m);
		
		/**	令容量 j=r+kw 
			f[j]= f[r+kw] 
				= max{ f[r+qw]+(k-q)*v | q=0,1...k }
				= max{ f[r+qw]-q*v     | q=0,1...k } + k*v	
		*/
		for(int r=0;r<w;r++){	//枚举余数r		
			int head=0,tail=-1,k=(W-r)/w;
			for(int q=0;q<=k;q++){	//枚举倍数q
				while(head<=tail && f[r+q*w]-q*v>=Que2[tail]) tail--;
				Que[++tail]=q;
				Que2[tail]=f[r+q*w]-q*v;
		
				if(head<=tail && q-Que[head]>m) head++;
			
				f[r+q*w]=Que2[head]+q*v;
			}
		}
	}
	printf("%d",f[W]);
	return 0;
}

上面代码中,Que是“下标”队列,Que2是对应的最优值队列,元素一一对应,Que2[i]=f[r+Que[i]*w]-Que[i]*v ,但是按这种方式改成只用一个队列的方式就有问题了(只列出更改部分)

		for(int r=0;r<w;r++){	//枚举余数r		
			int head=0,tail=-1,k=(W-r)/w;
			for(int q=0;q<=k;q++){	//枚举倍数q
				while(head<=tail && f[r+q*w]-q*v>=f[r+Que[tail]*w]-Que[tail]*v) tail--;
				Que[++tail]=q;
	
				if(head<=tail && q-Que[head]>m) head++;
			
				f[r+q*w]=f[r+Que[head]*w]-Que[head]*v+q*v;
			}
		}
2024/3/5 04:38
加载中...