hdu4374 单调队列优化dp

2015-07-20 17:10:03 来源: 作者: 浏览: 2

?

题意就不多说了,直接说思路吧;

对每一层的点都有两种方式到达(左边不超过T步 或右边不超过T步) 对这两种方式容易得出

?

dp[i][j] = max( dp[i][j] , dp[i - 1][k] + sum[i][j] - sum[i][k - 1] ) ; //从上层的k向右走过来 dp[i][j] = max( dp[i][j] , dp[i - 1][k] + sum[i][k] - sum[i][j - 1] ) ; //从上层的k点向左走来

?

因为每一层的sum是定的 所以 只要求满足条件的dp【i-1】【k】-sum[i][k-1]的最大值就行 这就用到单调队列来优化了

?

?

#include
  
   
#include
   
     #include
     
     using namespace std
     ; #define INF -0x3f3f3f3f 
      int sum
     [20100
     ],num
     [110
     ][20100
     ],id
     [20100
     ],dp
     [110
     ][20100
     ],map
     [10010
     ]; int max
     (int a
     ,int b
     ) { return a
     >b
     ?a
     :b
     ; } int main() { int n
     ,m
     ,i
     ,j
     ,x
     ,T
     ; while(~scanf
     ("%d%d%d%d"
     ,&n
     ,&m
     ,&x
     ,&T
     )) { for(i
     =1
     ;i
     <=n
     ;i
     ++) for(j
     =1
     ;j
     <=m
     ;j
     ++) { scanf
     ("%d"
     ,&num
     [i
     ][j
     ]); dp
     [i
     ][j
     ]=INF
     ; } dp
     [1
     ][x
     ]=num
     [1
     ][x
     ]; for(i
     =x
     -1
     ;i
     >=1
     &&x
     -i
     <=T
     ;i
     --) dp
     [1
     ][i
     ]=dp
     [1
     ][i
     +1
     ]+num
     [1
     ][i
     ]; for(i
     =x
     +1
     ;i
     <=m
     &&i
     -x
     <=T
     ;i
     ++) dp
     [1
     ][i
     ]=dp
     [1
     ][i
     -1
     ]+num
     [1
     ][i
     ]; int front
     ,top
     ; sum
     [0
     ]=0
     ; for(i
     =2
     ;i
     <=n
     ;i
     ++) { for(j
     =1
     ;j
     <=m
     ;j
     ++) sum
     [j
     ]=sum
     [j
     -1
     ]+num
     [i
     ][j
     ]; front
     =0
     ,top
     =0
     ; for(j
     =1
     ;j
     <=m
     ;j
     ++) { int tt
     =dp
     [i
     -1
     ][j
     ]-sum
     [j
     -1
     ]; while(front
     <top
     &&tt
     >map
     [top
     ]) top
     --; id
     [++top
     ]=j
     ; map
     [top
     ]=tt
     ; while(j
     -T
     >id
     [front
     +1
     ]&&front
     <top
     ) front
     ++; dp
     [i
     ][j
     ]=max
     (dp
     [i
     ][j
     ],map
     [front
     +1
     ]+sum
     [j
     ]); } front
     =0
     ,top
     =0
     ; sum
     [m
     +1
     ]=0
     ; for(j
     =m
     ;j
     >=1
     ;j
     --) sum
     [j
     ]=sum
     [j
     +1
     ]+num
     [i
     ][j
     ]; for(j
     =m
     ;j
     >=1
     ;j
     --) { int tt
     =dp
     [i
     -1
     ][j
     ]-sum
     [j
     +1
     ]; while(front
     <top
     &&tt
     >map
     [top
     ]) top
     --; id
     [++top
     ]=j
     ; map
     [top
     ]=tt
     ; while(front
     <top
     &&id
     [front
     +1
     ]>j
     +T
     ) front
     ++; dp
     [i
     ][j
     ]=max
     (dp
     [i
     ][j
     ],map
     [front
     +1
     ]+sum
     [j
     ]); } } int Max
     =INF
     ; for(i
     =1
     ;i
     <=m
     ;i
     ++) if(dp
     [n
     ][i
     ]>Max
     ) Max
     =dp
     [n
     ][i
     ]; printf
     ("%d\n"
     ,Max
     ); } return 0
     ; }
    
   
  

?

-->

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: