zoukankan      html  css  js  c++  java
  • Code[VS] 2152 滑雪题解

    Code[VS] 2152 滑雪题解

    题目描述 Description

    trs喜欢滑雪。他来到了一个滑雪场,这个滑雪场是一个矩形,为了简便,我们用r行c列的矩阵来表示每块地形。为了得到更快的速度,滑行的路线必须向下倾斜。
    例如样例中的那个矩形,可以从某个点滑向上下左右四个相邻的点之一。例如24-17-16-1,其实25-24-23…3-2-1更长,事实上这是最长的一条。

    输入描述 Input Description

    输入文件

    第1行: 两个数字r,c(1<=r,c<=100),表示矩阵的行列。
    第2..r+1行:每行c个数,表示这个矩阵。

    输出描述 Output Description

    输出文件

    仅一行: 输出1个整数,表示可以滑行的最大长度。

    样例输入 Sample Input

    5 5
    1 2 3 4 5
    16 17 18 19 6
    15 24 25 20 7
    14 23 22 21 8
    13 12 11 10 9

    样例输出 Sample Output

    25

    数据范围及提示 Data Size & Hint

    1s

     ————————————————————————————分割线————————————————————————————

    初见此题时,便想到记忆化DFS的方法,由于本题数据较小,可以轻松过。但是,当数据再大一点,再用递归便不太合适。那么,如何用非递归方法解决这个问题?
    仔细观察问题,发现最长上升子序列问题与本题有几分相像,如何将二维问题转为一维问题是解题的关键。
    我们将每个山依照高度排序放置到一个一维数组中,并记录下原始的坐标,这时再进行最长上升子序列,只需要在其中,加入两个山是否相邻的判断即可 。
    此方法可以避免,数据规模较大时,由于递归层数过深导致的堆栈溢出。同时也十分容易理解。 
     
    代码如下:
     1 //Code By DrSHHHS
     2 
     3 #include "bits/stdc++.h"
     4 
     5 using namespace std ;
     6 
     7 const int maxN = 10010 ;
     8 const int INF = 2147483647 ;
     9 
    10 struct Slide {int x , y , val ;};
    11 
    12 Slide arr[maxN] ;
    13 int f[maxN] ; 
    14 
    15 bool cmp ( Slide a , Slide b ) { return a.val > b.val ;}
    16 int Abs ( int x ) { return x>0?x:-x ;}
    17 int Max ( int a , int b ){ return a>b?a:b ; }
    18 
    19 bool Judge ( int p1 , int p2 ) {//判断两座山是否相邻且严格下降 
    20          if (( Abs ( arr[p1].x - arr[p2].x) + Abs ( arr[p1].y - arr[p2].y) )==1 && arr[p2].val > arr[p1].val) return true ;
    21          else                                                                                     return false ;
    22 }
    23 
    24 int main ( ) {
    25          int N , M , tmp , K = 0 ,ans = -INF ;
    26          
    27          scanf("%d%d",&N ,&M ) ;
    28          for ( int i=1 ; i<=N ; ++i ){
    29                    for ( int j=1 ; j<=M ; ++j ){
    30                              K++;
    31                              scanf( "%d" , &tmp ) ;//将二维数组读入一个一维数组arr中 
    32                              arr[K].val = tmp ;
    33                              arr[K].x = i ;arr[K].y = j ;//记录原始坐标 
    34                    }
    35          }
    36          
    37          sort ( arr+1 , arr+K+1 , cmp ) ;//排序 
    38          
    39          f[1] = 1 ;
    40 
    41          for ( int i=2 ; i<=K ; ++i ){//最长下降子序列 
    42                    for ( int j=1 ; j<=i-1 ; ++j ) {
    43                              if ( Judge ( i , j ) ){//判断相邻切严格下降 
    44                                         f[i] = Max ( f[i] , f[j] )  ; 
    45                              }     
    46                    }
    47                    f[i] = f[i] + 1 ; 
    48          }
    49 
    50          for ( int i=1 ; i<=K ; ++i ){//找最大值 
    51                    ans = Max ( f[i] , ans ) ;
    52          }
    53          
    54          printf ( "%d" , ans ) ;
    55          
    56          return 0 ;
    57 } 
    PS : 这个问题可视为最长下降子序列在二维中的拓展。
     
    顺便附上记忆化搜索的代码,如下:
     1 #include "bits/stdc++.h"
     2 
     3 using namespace std ;
     4 const int maxN = 110 ;
     5 
     6 int h[maxN][maxN] , f[maxN][maxN] ;
     7 int n, m, ans = 1;
     8 
     9 int DFS(int x, int y)
    10 {
    11     if( f[x][y] )return f[x][y];
    12     f[x][y] = 1;
    13     if(x > 1 && h[x][y] < h[x - 1][y])f[x][y] = max(f[x][y], DFS(x - 1, y) + 1);
    14     if(y > 1 && h[x][y] < h[x][y - 1])f[x][y] = max(f[x][y], DFS(x, y - 1) + 1);
    15     if(x < n && h[x][y] < h[x + 1][y])f[x][y] = max(f[x][y], DFS(x + 1, y) + 1);
    16     if(y < m && h[x][y] < h[x][y + 1])f[x][y] = max(f[x][y], DFS(x, y + 1) + 1);
    17     ans = max(ans, f[x][y]);
    18     return f[x][y];
    19 }
    20 int main()
    21 {
    22     scanf("%d%d", &n, &m);
    23     for ( int i = 1 ; i <= n ; i++ )
    24         for ( int j = 1 ; j <= m ; j++ )
    25             scanf( "%d" , &h[i][j] ) ;
    26     for(int i = 1 ; i <= n ; i++ )
    27         for(int j = 1 ; j <= m ; j++ )
    28             f[i][j] = DFS( i , j ) ;
    29     printf("%d", ans);
    30 
    31     return 0;
    32 }

    2016-09-14 15:45:58

    (完)

  • 相关阅读:
    linux防止sshd被爆破(安装denyhosts)
    记一次网站服务器搬迁实录
    用几条shell命令快速去重10G数据
    如何让你的scrapy爬虫不再被ban之二(利用第三方平台crawlera做scrapy爬虫防屏蔽)
    同时运行多个scrapy爬虫的几种方法(自定义scrapy项目命令)
    如何让你的scrapy爬虫不再被ban
    scrapy爬虫成长日记之将抓取内容写入mysql数据库
    scrapy爬虫成长日记之创建工程-抽取数据-保存为json格式的数据
    python将json格式的数据转换成文本格式的数据或sql文件
    shell脚本去重的几种方法
  • 原文地址:https://www.cnblogs.com/shadowland/p/5872495.html
Copyright © 2011-2022 走看看