hdu 4374 (单调队列+dp)
d[i][j]表示i行j列格子可以得到的最大值
顺着来的时候
d[i][j]=max(d[i-1][k]+sum[k...j])=max(d[i-1][k]-sum[1..k-1]+sum[1...j]) sum[1...j]是固定值 只要找d[i-1][k]+sum[1...k] 的最大值就可以了
找法就是维护一个单调递减的队列,每次加入一个值进去就把队列值后面小于它的点都删掉,把前面j-k>t的点删掉(走的步数大于t步),d[i][j]=队首值+sum[1...j]
逆着来的时候
d[i][j]=max(d[i-1][k]+sum[k...j])=max(d[i-1][k]+sum[1...k])-sum[1...j-1] sum[1...k]是固定值 只要找d[i-1][k]-sum[1...j] 的最大值就可以了
维护一个单调递减的队列,每次加入一个值进去就把队列值后面小于它的点都删掉,把前面j-k>t的点删掉(走的步数大于t步),d[i][j]=队首值-sum[1...k]
1 #include<iostream> 2 #include<string.h> 3 #include<stdio.h> 4 #include<queue> 5 using namespace std; 6 #define INF -9999999 7 int a[102][10002],d[102][10002],sum[102][10002]; 8 9 struct node 10 { 11 int zhi,wei; 12 } q[10002]; 13 14 15 int main() 16 { 17 int k,n,m,x,t; 18 while(~scanf("%d%d%d%d",&n,&m,&x,&t)) 19 { 20 for(int i=1; i<=n; i++) 21 for(int j=1; j<=m; j++) 22 scanf("%d",&a[i][j]); 23 for(int i=1; i<=n; i++) 24 for(int j=1; j<=m; j++) 25 d[i][j]=INF; 26 memset(sum,0,sizeof(sum)); 27 d[1][x]=a[1][x]; 28 for(int i=1; i<=t&&i+x<=m; i++) 29 d[1][i+x]=max(d[1][x+i],d[1][x+i-1]+a[1][x+i]); 30 31 for(int i=1; i<=t&&x-i>=1; i++) 32 d[1][x-i]=max(d[1][x-i],d[1][x-i+1]+a[1][x-i]); 33 34 for(int i=2; i<=n; i++) 35 { 36 for(int j=1; j<=m; j++) 37 sum[i][j]=sum[i][j-1]+a[i][j]; 38 39 int front1=0,rear=0; 40 for(int j=1; j<=m; j++) 41 { 42 43 int temp=d[i-1][j]-sum[i][j-1]; 44 while(front1<rear&&q[rear-1].zhi<temp) 45 rear--; 46 q[rear].zhi=temp; 47 q[rear++].wei=j; 48 49 while(front1<rear&&j-q[front1].wei>t) 50 front1++; 51 52 d[i][j]=max(d[i][j],q[front1].zhi+sum[i][j]); 53 54 } 55 front1=0,rear=0; 56 for(int j=m; j>=1; j--) 57 { 58 int temp=d[i-1][j]+sum[i][j]; 59 while(q[rear-1].zhi<temp&&front1<rear) 60 rear--; 61 q[rear].zhi=temp; 62 q[rear++].wei=j; 63 64 while(front1<rear&&q[front1].wei-j>t) 65 front1++; 66 d[i][j]=max(d[i][j],q[front1].zhi-sum[i][j-1]); 67 } 68 69 } 70 int ans=0; 71 for(int j=0; j<=n; j++) 72 for(int i=1; i<=m; i++) 73 ans=max(d[n][i],ans); 74 75 printf("%d\n",ans); 76 } 77 return 0; 78 }