码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 3926 Parade 单调队列优化DP

时间:2014-07-31 12:22:36      阅读:269      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   io   for   ar   div   

来源:http://poj.org/problem?id=3926

题意:行n <= 100, 列m <= 10000,类似于数字三角形,一个人要从底下往上走,每层中可以左右走,但选定方向不能回头(向左不能再向右),每经过一段获得该段的一个值,并走了该段的距离,在同一层走的距离不能超过k。问走到最顶头,获得的总值最大是多少。

分析:dp[i][j]表示走到第i行第j列,获得的值最大为多少。则dp[i][j] = max(dp[i+1][p] + sum(p to j)),sum(p to j)表示第i行从第p列到第j列的值的和,同时p需要满足abs(p-j) <= k。前缀和处理sum,枚举i,j,p,这样是o(nm^2)的复杂度,超时。

如果我们只考虑从左往右走,那么就是类似求有长度上限的最大子段和的模型了。sum(k)表示第i行前k列的前缀和,改写转移方程 dp[i][j] = max(dp[i+1][p] + sum(j) - sum(p)) = max(dp[i+1][p] - sum(p)) + sum(j),这下很清楚了,前一项就可以用单调队列来维护,使得状态转移的复杂度降到均摊o(1)。然后从右往左走再做一遍就可以了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 int n, m, k;
 7 int a[120][10100], b[120][10100], dp[120][10100];
 8 struct que{
 9     int v, d;
10 } q[10100];
11 inline int in(){
12     char ch = getchar();
13     while((ch < 0 || ch > 9) && ch != -) ch = getchar();
14     bool flag = false;
15     if (ch == -){
16         flag = true;
17         ch = getchar();
18     }
19     int ans = 0;
20     while(ch >= 0 && ch <= 9){
21         ans = ans*10 + ch-0;
22         ch = getchar();
23     }
24     if (flag) return -ans;
25     return ans;
26 }
27 int main()
28 {
29     while(scanf("%d%d%d", &n, &m, &k) && (n+m+k))
30     {
31         for (int i = 0; i <= n; i++)
32             for (int j = 0; j < m; j++)
33                 a[i][j] = in();
34         for (int i = 0; i <= n; i++)
35             for (int j = 0; j < m; j++)
36                 b[i][j] = in();
37         for (int j = 0; j <= m; j++)
38             dp[n+1][j] = 0;
39         for (int i = n; i >= 0; i--){
40             int sum, head, tail, dis;
41             sum = head = tail = dis = 0;
42             dp[i][0] = dp[i+1][0];
43             q[tail].v = dp[i][0];
44             q[tail++].d = 0;
45             for (int j = 1; j <= m; j++){
46                 sum += a[i][j-1];
47                 dis += b[i][j-1];
48                 while(head < tail && dis - q[head].d > k) head ++;
49                 while(head < tail && q[tail-1].v <= dp[i+1][j] - sum) tail --;
50                 q[tail].d = dis;
51                 q[tail++].v = dp[i+1][j] - sum;
52                 dp[i][j] = q[head].v + sum;
53             }
54             sum = head = tail = dis = 0;
55             q[tail].v = dp[i+1][m];
56             q[tail++].d = 0;
57             for (int j = m-1; j >= 0; j--){
58                 sum += a[i][j];
59                 dis += b[i][j];
60                 while(head < tail && dis - q[head].d > k) head ++;
61                 while(head < tail && q[tail-1].v <= dp[i+1][j] - sum) tail --;
62                 q[tail].d = dis;
63                 q[tail++].v = dp[i+1][j] - sum;
64                 if (q[head].v + sum > dp[i][j]) dp[i][j] = q[head].v + sum;
65             }
66         }
67         int ans = 0;
68         for (int i = 0; i <= m; i++)
69             if (dp[0][i] > ans) ans = dp[0][i];
70         printf("%d\n", ans);
71     }
72     return 0;
73 }

 

POJ 3926 Parade 单调队列优化DP,布布扣,bubuko.com

POJ 3926 Parade 单调队列优化DP

标签:style   blog   http   color   io   for   ar   div   

原文地址:http://www.cnblogs.com/james47/p/3880218.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!