hdu 3401 单调队列优化dp

dp[i][j]表示第i天有j张彩票,因为隔w+1天才能买(卖),
dp[i][j](1<i<=w+1,0<=j<=maxp)都要预处理出来,每一天的j=0也要预处理出来。
因为预处理出来了那么i-w-1天的一定是相对i(w+2<=i<=n)天来说的最优解;(if不是 i-w-1是i-w到i-1是最优的话说明,从i-w-1开始就没有再买或卖,第i天才能买或卖,那么从 i-w到i-1天的dp值都和i-w-1天一样了,所以i-w-1天是最优)
所以当买的时候
dp[i][j]=max(dp[i-w-1][k]-ap[i]*(j-k))//0<=k<=j;

dp[i-w-1][k]-ap[i]*(j-k)=dp[i-w-1][k]-ap[i]*j+ap[i]*k;ap[i]*j都是一样,只需单调队列维护dp[i-w-1][k]+ap[i]*k最大的就好

因为k是<=j的所以处理dp[i][j]时顺便把对应的dp[i-w-1][j]的值放进队列//不会出现在队列的dp[i-w-1][k](k>j)影响dp[i][j]

而卖的时候dp[i-w-1][k](k>=j)会影响dp[i][j]所以j倒着循环
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int dp[2005][2005],ap[2005],as[2005],bp[2005],bs[2005],n,p,w;
struct node
{
	int num,val; 
};
node q[10005];
int main()
{
   int t;cin>>t;	
   for(int z=1;z<=t;z++)
   {
         	cin>>n>>p>>w;
          for(int i=0; i<=n; i++)
            for(int j=0; j<=p; j++) dp[i][j]=-1e9;
        for(int i=1; i<=n; i++) scanf("%d%d%d%d",ap+i,bp+i,as+i,bs+i);
        for(int i=1; i<=n; i++) dp[i][0]=0;
         	for(int i=1;i<=w+1;i++)
         	for(int j=1;j<=as[i];j++)
         	dp[i][j]=-j*ap[i];	
			 for(int j=1;j<=p;j++)
         	for(int i=2;i<=w+1;i++)
         dp[i][j]=max(dp[i-1][j],dp[i][j]);
			 for(int i=w+2;i<=n;i++)
         	{
         		 int head=0,tail=-1;
         	  for(int j=0;j<=p;j++)
         	  { 
         	    dp[i][j]=max(dp[i][j],dp[i-1][j]);
				 while(head<=tail&&(ap[i]*(j)+dp[i-1-w][j])>=q[tail].val )tail--;
				q[++tail].val=ap[i]*j+dp[i-1-w][j],q[tail].num=j;
				 while(head<=tail&&j-q[head].num>as[i])head++;//?=
         	    dp[i][j]=max(dp[i][j],q[head].val-ap[i]*j);
			  }
			 	 head=0,tail=-1;
         	  for(int j=p;j>=0;j--)
         	  { 
				 while(head<=tail&&(bp[i]*(j)+dp[i-1-w][j])>=q[tail].val )tail--;
				q[++tail].val=bp[i]*j+dp[i-1-w][j],q[tail].num=j;
				 while(head<=tail&&q[head].num-j>bs[i])head++;
         	   dp[i][j]=max(dp[i][j],q[head].val-bp[i]*j);
			  }
			}
		int ans=0;
		for(int i=0;i<=p;i++)
		ans=max(ans,dp[n][i]);	  
         cout<<ans<<endl;
   }
   return 0;
}

猜你喜欢

转载自blog.csdn.net/Bluelanzhan/article/details/80432820