HDU 4374 One hundred layer(DP+单调队列优化)

题目链接

比赛的时侯非常暴力来了个N*M*T的算法,状态方程虽然好想,不会优化。。认真学习一下单调队列优化,看了很多博客+题解,其实原理也不难理解。

这个题状态转移,从左边来的 dp[i][j] =  dp[i-1][k] + dis(k,j) 先预处理出一个sum数组存每一行前i个元素的和,dp[i][j] = dp[i-1][k] + sum[i][j]-sum[i][k-1];

这就可以用单调队列了,在队列首部存放dp[i-1][k]-sum[i][k-1]最大值的下标。明白了原理后,看了一份题解,想了好一会为什么队头总是最大的,问了下学长,这个队列的关键是队头,小的元素可以直接覆盖进入队列,而不是插入进入队列,所以不可能存在队列中元素比队头大的。看了好久,最近学习效率好低啊。。。

代码参考题解。

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4 int p[110][10001],dp[111][10001];
 5 int sum[110][10001],que[10001];
 6 int max(int a,int b)
 7 {
 8     return a > b ? a:b;
 9 }
10 int main()
11 {
12     int i,j,n,m,x,t,ans,str,end;
13     while(scanf("%d%d%d%d",&n,&m,&x,&t)!=EOF)
14     {
15         memset(dp,128,sizeof(dp));
16         for(i = 1; i <= n; i ++)
17         {
18             for(j = 1; j <= m; j ++)
19             {
20                 scanf("%d",&p[i][j]);
21                 sum[i][j] = sum[i][j-1] + p[i][j];
22             }
23         }
24         for(i = x; i >= x - t && i >= 1; i --)
25             dp[1][i] = sum[1][x] - sum[1][i-1];
26         for(i = x + 1; i <= x + t && i <= m; i ++)
27             dp[1][i] = sum[1][i] - sum[1][x-1];
28         for(i = 2;i <= n;i ++)
29         {
30             str = end = 0;
31             for(j = 1;j <= m;j ++)
32             {
33                 //覆盖进入队列
34                 while(str < end&&dp[i-1][j]-sum[i][j-1]>dp[i-1][que[end-1]]-sum[i][que[end-1]-1])
35                 end --;
36                 que[end++] = j;
37                 dp[i][j] = dp[i-1][que[str]]+sum[i][j]-sum[i][que[str]-1];
38                 if(j - que[str] >= t)//维护队列在t范围内
39                 str ++;
40             }
41             str = end = 0;
42             for(j = m;j >= 1;j --)
43             {
44                 while(str < end&&dp[i-1][j]+sum[i][j]>dp[i-1][que[end-1]]+sum[i][que[end-1]])
45                 end -- ;
46                 que[end++] = j;
47                 dp[i][j] = max(dp[i][j],dp[i-1][que[str]]+sum[i][que[str]]-sum[i][j-1]);
48                 if(que[str] - j >= t)
49                 str++;
50             }
51         }
52         ans = dp[n][1];
53         for(i = 2;i <= m;i ++)
54         {
55             ans = max(ans,dp[n][i]);
56         }
57         printf("%d\n",ans);
58     }
59     return 0;
60 }
posted @ 2012-08-19 17:47  Naix_x  阅读(232)  评论(0编辑  收藏  举报