单调队列优化DP :
dp[ i ] [ j ] = max{ dp[ i-1 ] [ j ] , dp[ i - w -1 ] [ k ] - ( j - k )*ap[ i ] , dp [ i - w - 1 ] [ k ] + ( k - j )*bp[ i ] }
后两项 dp [ i - w - 1 ][ k ] + k* xx - j * xx 且 abs( j - x) < yy 可以维护一个单调递减的队列。。。
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
#include <iostream> #include <cstring> #include <cstdio> #include <queue> #include <algorithm> using namespace std; const int maxn=2200; int N,P,W,dp[maxn][maxn],ap[maxn],bp[maxn],as[maxn],bs[maxn]; struct node { int val,pos; }que[maxn]; void solve() { int head,tail,pre; memset(dp,0xcf,sizeof(dp)); for(int i=1;i<=N;i++) { for(int j=0;j<=min(as[i],P);j++) { dp[i][j]=-ap[i]*j; } } for(int i=2;i<=N;i++) { for(int j=0;j<=P;j++) { dp[i][j]=max(dp[i-1][j],dp[i][j]); } } for(int i=W+2;i<=N;i++) { pre=i-W-1; head=0,tail=-1; for(int j=0;j<=P;j++)///buy { dp[i][j]=max(dp[i-1][j],dp[i][j]); node temp; temp.val=dp[pre][j]+j*ap[i]; temp.pos=j; while(head<=tail&&que[tail].val<temp.val) tail--; que[++tail]=temp; while(head<=tail&&(j-que[head].pos)>as[i]) head++; if(head<=tail) { dp[i][j]=max(dp[i][j],que[head].val-j*ap[i]); } } head=0;tail=-1; for(int j=P;j>=0;j--)///sell { dp[i][j]=max(dp[i-1][j],dp[i][j]); node temp; temp.val=dp[pre][j]+bp[i]*j; temp.pos=j; while(head<=tail&&que[tail].val<temp.val) tail--; que[++tail]=temp; while(head<=tail&&(que[head].pos-j)>bs[i]) head++; if(head<=tail) { dp[i][j]=max(dp[i][j],que[head].val-bp[i]*j); } } } } int main() { int cas; scanf("%d",&cas); while(cas--) { scanf("%d%d%d",&N,&P,&W); for(int i=1;i<=N;i++) scanf("%d%d%d%d",ap+i,bp+i,as+i,bs+i); solve(); printf("%d\n",dp[N][0]); } return 0; }