• PepperLa's Boast(单调队列优化二维dp)


    PepperLa's Boast(单调队列优化二维dp)

     

    题意:一个人在(1,1)点处,由于这个n*m的二维空间着火了,他要从(1,1)点逃到(n,m)点。给出 n*m 矩阵内每一个坐标的的值代表这里的空气,限制是空气小于等于零的地方不能呼吸。这个人的每一步只可以走到三个方向:(x+1,y+1)  or (x+1,y) or (x,y+1) ,每次可以走一步到有空气的地方进行换气(呼吸),也可以消耗 U 体积的空气走 K 步到有空气的地方进行换气呼吸。问当到达(n,m)点时,这个人的肺中最多存有多少空气

    题解:

     做到这题的时候还没有掌握单调队列QAQ

    所以WA:

      1 // 又是看了一晚上的dp不知道思路错在哪里
      2 // 其实是不可以这么一步一步贪心去取的最大值的
      3 // 因为我到当前点i,j才减上一个点要去掉的u
      4 // 有可能之前的大,但是他要减u,到这儿变小了
      5 // 而之前小的, 但是他中间不经过无空气地带, 到这儿不减u, 这样得到的答案反而比上面的值打
      6 // 所以, 很明显这要再来一重循环(跑每一个到当前点距离不超过点)去一个个试试了
      7 // 这复杂度应该是O(n*m*k),所以要优化了
      8 
      9 #include <iostream>
     10 #include <bits/stdc++.h>
     11 using namespace std;
     12 typedef long long ll;
     13 const int maxn = 1e3+10;
     14 
     15 ll ans;
     16 int n,m;
     17 ll k,u;
     18 ll dp[maxn][maxn];
     19 ll a[maxn][maxn];
     20 ll z[maxn][maxn];
     21 
     22 struct node{
     23     int id;
     24     int u,v;
     25 };
     26 
     27 bool cmp(node x, node y){
     28     if( x.u==y.u ) return x.v>y.v;
     29     return x.u>y.u;
     30 }
     31 
     32 int judge(int i,int j){
     33     node f[5];
     34     f[1].id=1; f[1].u=dp[i-1][j-1]; f[1].v=z[i-1][j-1];
     35     f[2].id=2; f[2].u=dp[i-1][j]; f[2].v=z[i-1][j];
     36     f[3].id=3; f[3].u=dp[i][j-1]; f[3].v=z[i][j-1];
     37     sort(f+1,f+1+3,cmp);
     38     return f[1].id;
     39 }
     40 
     41 int main()
     42 {
     43     while( ~scanf("%d%d%lld%lld",&n,&m,&k,&u)){
     44         memset(dp,-1,sizeof(dp));
     45         for(int i=1;i<=n;i++){
     46             for(int j=1;j<=m;j++){
     47                 scanf("%lld",&a[i][j]);
     48             }
     49         }
     50 
     51         dp[1][1] = a[1][1];
     52         if( a[1][1]>=u ) z[1][1] = k;
     53         else z[1][1] = 0;
     54 
     55         for(int i=1;i<=n;i++){
     56             for(int j=1;j<=m;j++){
     57                 if( i==1 && j==1 ) continue;
     58                 else if( i==1 ){
     59                     if( dp[i][j-1]<=0 ){
     60                         continue;
     61                     }
     62 
     63                     if( a[i][j]<=0 ){
     64                         z[i][j] = z[i][j-1]-1;
     65                         if( z[i][j]<=0 ){
     66                             dp[i][j] = -1;
     67                         }else{
     68                             dp[i][j] = dp[i][j-1];
     69                         }
     70                     }
     71                     else{
     72                         if( a[i][j-1]>0 ) dp[i][j] = dp[i][j-1]+a[i][j];
     73                         else dp[i][j] = dp[i][j-1]-u+a[i][j];
     74 
     75                         if( dp[i][j]>=u ) z[i][j] = k;
     76                         else z[i][j] = 0;
     77                     }
     78                 }
     79                 else if( j==1 ){
     80                     if( dp[i-1][j]<=0 ) continue;
     81 
     82                     if( a[i][j]<=0 ){
     83                         z[i][j] = z[i-1][j]-1;
     84                         if( z[i][j]<=0 ){
     85                             dp[i][j] = -1;
     86                         }else{
     87                             dp[i][j] = dp[i-1][j];
     88                         }
     89                     }
     90                     else{
     91                         if( a[i-1][j]>0 ) dp[i][j] = dp[i-1][j]+a[i][j];
     92                         else dp[i][j] = dp[i-1][j]-u+a[i][j];
     93                         if( dp[i][j]>=u ) z[i][j] = k;
     94                         else z[i][j] = 0;
     95                     }
     96                 }
     97                 else{
     98                     if( a[i][j]<=0 ){
     99                         int f = judge(i,j);
    100                         if( f==1 ){
    101                             if( dp[i-1][j-1]<=0 ) continue;
    102 
    103                             z[i][j] = z[i-1][j-1]-1;
    104                             if( z[i][j]<=0 ){
    105                                 dp[i][j] = -1;
    106                             }
    107                             else{
    108                                 dp[i][j] = dp[i-1][j-1];
    109                             }
    110                         }
    111                         else if( f==2 ){
    112                             if( dp[i-1][j]<=0 ) continue;
    113 
    114                             z[i][j] = z[i-1][j]-1;
    115                             if( z[i][j]<=0 ){
    116                                 dp[i][j] = -1;
    117                             }
    118                             else{
    119                                 dp[i][j] = dp[i-1][j];
    120                             }
    121                         }
    122                         else if( f==3 ){
    123                             if( dp[i][j-1]<=0 ) continue;
    124 
    125                             z[i][j] = z[i][j-1]-1;
    126                             if( z[i][j]<=0 ){
    127                                 dp[i][j] = -1;
    128                             }
    129                             else{
    130                                 dp[i][j] = dp[i][j-1];
    131                             }
    132                         }
    133                     }
    134                     else{
    135                         int f = judge(i,j);
    136                         if( f==1 ){
    137                             if( dp[i-1][j-1]<=0 ) continue;
    138 
    139 
    140                             if( a[i-1][j-1]>0 ){
    141                                 z[i][j] =  k;
    142                                 dp[i][j] = dp[i-1][j-1]+a[i][j];
    143                             }
    144                             else{
    145                                 dp[i][j] = dp[i-1][j-1]-u+a[i][j];
    146                                 if( dp[i][j]>=u ) z[i][j] = k;
    147                                 else z[i][j] = 0;
    148                             }
    149                         }
    150                         else if( f==2 ){
    151                             if( dp[i-1][j]<=0 ) continue;
    152 
    153                             if( a[i-1][j]>0 ){
    154                                 z[i][j] =  k;
    155                                 dp[i][j] = dp[i-1][j]+a[i][j];
    156                             }
    157                             else{
    158                                 dp[i][j] = dp[i-1][j]-u+a[i][j];
    159                                 if( dp[i][j]>=u ) z[i][j] = k;
    160                                 else z[i][j] = 0;
    161                             }
    162                         }
    163                         else if( f==3 ){
    164                             if( dp[i][j-1]<=0 ) continue;
    165 
    166                             if( a[i][j-1]>0 ){
    167                                 z[i][j] =  k;
    168                                 dp[i][j] = dp[i][j-1]+a[i][j];
    169                             }
    170                             else{
    171                                 dp[i][j] = dp[i][j-1]-u+a[i][j];
    172                                 if( dp[i][j]>=u ) z[i][j] = k;
    173                                 else z[i][j] = 0;
    174                             }
    175                         }
    176                     }
    177                 }
    178             }
    179         }
    180         printf("%lld
    ",dp[n][m]);
    181     }
    182     return 0;
    183 }
    View Code

    AC_Code:可以先看一看我的这篇博客-->here

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn=1e3+10;
     5 const int inf = 0x3f3f3f3f;
     6 
     7 struct node{
     8     ll val;
     9     int idx;
    10 };
    11 int n,m,k,u;
    12 int a[maxn][maxn];
    13 ll dp[maxn][maxn];
    14 deque<node>col_q[maxn], row_q;
    15 
    16 void _max(ll &x, ll y ){
    17     if( x<y ) x=y;
    18 }
    19 //纵向每列建一个列单调队列,在每行从左到右转移时候再建一个行单调队列,入队的都是列单调队列的队首元素
    20 //为什么呢?因为从左边或者从左上转移过来,都是用单调队列后从左边转移过来啊
    21 
    22 int main()
    23 {
    24     memset(dp,-1,sizeof(dp));
    25     while( ~scanf("%d%d%d%d",&n,&m,&k,&u) ){
    26         for(int i=1;i<=n;i++){
    27             for(int j=1;j<=m;j++){
    28                 scanf("%d",&a[i][j]);
    29                 dp[i][j] = -1;
    30             }
    31         }
    32         dp[1][1] = a[1][1];
    33         for(int i=1;i<=m;i++) col_q[i].clear();
    34         for(int i=1;i<=n;i++){
    35             row_q.clear();
    36             for(int j=1;j<=m;j++){
    37                 while( col_q[j].size() && col_q[j].front().idx<i-k ) col_q[j].pop_front();//注意这里是<i-k, 不是<=i-k,举个栗子就知道了从1走5步不是到5是到6,那么从6退5补是到6-5=1处
    38                 while( row_q.size() && row_q.front().idx<j-k ) row_q.pop_front();
    39 
    40                 if( a[i][j]>0 ){
    41                     if( dp[i-1][j]!=-1 ) _max(dp[i][j], dp[i-1][j]+a[i][j]);
    42                     if( dp[i][j-1]!=-1 ) _max(dp[i][j], dp[i][j-1]+a[i][j]);
    43                     if( dp[i-1][j-1]!=-1 ) _max(dp[i][j], dp[i-1][j-1]+a[i][j]);
    44 
    45                     if( col_q[j].size() ){
    46                         while( row_q.size() && row_q.back().val<=col_q[j].front().val ) row_q.pop_back();
    47                         row_q.push_back(node{col_q[j].front().val, j});//暂时加入上方的push here
    48                     }
    49                     if( row_q.size() ) _max(dp[i][j], row_q.front().val+a[i][j]-u);
    50                     if( col_q[j].size() ) row_q.pop_back();//然后删除, pop here
    51                 }
    52 
    53                 if( dp[i][j]>=u ){
    54                     while( col_q[j].size() && col_q[j].back().val<=dp[i][j]) col_q[j].pop_back();
    55                     col_q[j].push_back(node{dp[i][j], i});
    56                 }
    57 
    58                 if( col_q[j].size() ){
    59                     while( row_q.size() && row_q.back().val<=col_q[j].front().val ) row_q.pop_back();
    60                     row_q.push_back(node{col_q[j].front().val, j});
    61                 }
    62             }
    63         }
    64        printf("%lld
    ", dp[n][m]);
    65     }
    66     return 0;
    67 }
  • 相关阅读:
    进程和线程
    yum安装apache后更改worker模式
    (转)top命令详解
    虚拟机linux在关机不正常的情况下出现的问题
    mysql赋予用户权限grant all privileges on
    lampp自带mysql远程访问问题
    扫盲
    linux常用命令使用
    剑指Offer对答如流系列
    剑指Offer对答如流系列
  • 原文地址:https://www.cnblogs.com/wsy107316/p/14146361.html
Copyright © 2020-2023  润新知