http://acm.hdu.edu.cn/showproblem.php?pid=3401
1 5 2 0 2 1 1 1 2 1 1 1 3 2 1 1 4 3 1 1 5 4 1 1
3
/** hdu 3401 单调队列+DP http://blog.csdn.net/acm_ted/article/details/7909742 */ #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> using namespace std; #define MAX 2005 #define inf 0xfffff int T,MaxP,w; int APi[MAX],BPi[MAX],ASi[MAX],BSi[MAX]; int dp[MAX][MAX]; struct node { int x; int p; }q[2005],temp; int front,back; int main() { int cas; scanf("%d",&cas); while(cas--) { scanf("%d%d%d",&T,&MaxP,&w); for(int i=1;i<=T;++i) scanf("%d%d%d%d",APi+i,BPi+i,ASi+i,BSi+i); for(int i=0;i<=T;i++) for(int j=0;j<=MaxP;++j) dp[i][j]=-inf; for(int i=1;i<=w+1;i++) for(int j=0;j<=ASi[i];++j) dp[i][j]=(-APi[i]*j); for(int i=2;i<=T;i++) { for(int j=0;j<=MaxP;j++) dp[i][j]=max(dp[i][j],dp[i-1][j]); if(i<=w+1) continue; //买入 front=back=1; for(int j=0;j<=MaxP;j++) { temp.p=j; temp.x=dp[i-w-1][j]+APi[i]*j; while(front<back&&q[back-1].x<temp.x) back--; q[back++]=temp; while(front<back&&q[front].p+ASi[i]<j) front++; dp[i][j]=max(dp[i][j],q[front].x-APi[i]*j); } front=back=1; for(int j=MaxP;j>=0;j--) { temp.p=j; temp.x=dp[i-w-1][j]+BPi[i]*j; while(front<back&&q[back-1].x<temp.x) back--; q[back++]=temp; while(front<back&&q[front].p-BSi[i]>j) front++; dp[i][j]=max(dp[i][j],q[front].x-BPi[i]*j); } } int ans=0; for(int i=0;i<=MaxP;i++) ans=max(ans,dp[T][i]); printf("%d\n",ans); } return 0; }