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 }

 

posted @ 2014-09-06 20:09  galaxy77  阅读(240)  评论(0编辑  收藏  举报