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

(完)

时间: 2024-10-05 00:58:23

Code[VS] 2152 滑雪题解的相关文章

Code[VS]1690 开关灯 题解

Code[VS]1690 开关灯 题解  时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description: YYX家门前的街上有N(2<=N<=100000)盏路灯,在晚上六点之前,这些路灯全是关着的,六点之后,会有M(2<=m<=100000)个人陆续按下开关,这些开关可以改变从第i盏灯到第j盏灯的状态,现在YYX想知道,从第x盏灯到第y盏灯中有多少是亮着的(1<=i,j,x,y<=N) 输入描述 Input

Code[VS] 1022 覆盖 题解

Code[VS] 1022 覆盖 题解 Hungary Algorithm 题目传送门:Code[VS] 1022 题目描述 Description 有一个N×M的单位方格中,其中有些方格是水塘,其他方格是陆地.如果要用1×2的矩阵区覆盖(覆盖过程不容许有任何部分重叠)这个陆地,那么最多可以覆盖多少陆地面积. 输入描述 Input Description 输入文件的第一行是两个整数N,M  (1<=N,M<=100),第二行为一个整数K( K<=50),接下来的K行,每行两个整数X,Y表

Code[VS] 2370 LCA 题解

Code[VS] 2370 小机房的树 题解 LCA 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天,他们想爬到一个节点上去搞基,但是作为两只虫子,他们不想花费太多精力.已知从某个节点爬到其父亲节点要花费 c 的能量(从父亲节点爬到此节点也相同),他们想找出一条花费精力最短的路,以使得搞基的时候精力旺盛,他们找到你要你设计一个程序来找到这条路,要求你告诉他们最少需要花费多少精力 输入描述 I

[SHOI2002]滑雪-题解报告

题目描述 Michael 喜欢滑雪.这并不奇怪,因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael 想知道在一个区域中最长的滑坡.区域由一个二维数组给出.数组的每个数字代表点的高度.下面是一个例子: 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 一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度会减小.在上面的例子中,一条

LOJ6354 &amp; 洛谷4366:[Code+#4]最短路——题解

https://loj.ac/problem/6354 https://www.luogu.org/problemnew/show/P4366 题面见上面. 这题很妙,且可能是我傻,感觉这题不太好想. 前45pts很好骗就不说了. 朴素的建法是O(n^2+m)的,一个点都过不了. 然而事实上一个从x->y权值为w的边是可以被其他边取代的,我们可以把x拆成二进制,一位一位的修改最终到达y,此时经过的权值显然也是w. 也就是说,对于一个点x,我们只需要让他和x*2^k连边即可,这样就优化为O(nlo

POJ 1088 滑雪 记忆化优化题解

本题有人写是DP,不过和DP还是有点差别的,应该主要是记忆化 Momoization 算法. 思路就是递归,然后在递归的过程把计算的结果记录起来,以便后面使用. 很经典的搜索题目,这种方法很多题目考到的. 关键还是如何把代码写清晰工整了,O(∩_∩)O~. #include <stdio.h> const int MAX_N = 101; int R, C; int arr[MAX_N][MAX_N]; int tbl[MAX_N][MAX_N]; inline int max(int a,

点分治专题——bzoj 1468 &amp;bzoj 2152 题解

[前言]最近一直在忙着学算法,但是效果似乎不是很好.前段时间的树剖也快忘了= =.树套树没熟练,就开始写主席树了= =.更别说本身就不是很懂的莫比乌斯反演了.~~决定好好复习一下. [点分治的作用]套用SYC大神的话说是:用来解决树上路径点权统计问题. [大致流程] ①找出这颗树的重心. ②统计经过这个重心的答案 ③用重心把树割开 ④对每个"小树"做同样的事 [Q1--重心]其实找重心再进行计算只是为了不被卡链.什么是重心?就是当前树中的一个点K,使得MAX(SON[K])最小.SON

Code[VS]1021 玛丽卡题解

Code[VS]1021 玛丽卡题解 SPFA Algorithm 题目传送门:http://codevs.cn/problem/1021/ 题目描述 Description 麦克找了个新女朋友,玛丽卡对他非常恼火并伺机报复. 因为她和他们不住在同一个城市,因此她开始准备她的长途旅行. 在这个国家中每两个城市之间最多只有一条路相通,并且我们知道从一个城市到另一个城市路上所需花费的时间. 麦克在车中无意中听到有一条路正在维修,并且那儿正堵车,但没听清楚到底是哪一条路.无论哪一条路正在维修,从玛丽卡

Code[VS] 1332 上白泽慧音题解

Code[VS] 1332 上白泽慧音题解 Tarjan Algorithm 题目传送门:http://codevs.cn/problem/1332/ 题目描述 Description 在幻想乡,上白泽慧音是以知识渊博闻名的老师.春雪异变导致人间之里的很多道路都被大雪堵塞,使有的学生不能顺利地到达慧音所在的村庄.因此慧音决定换一个能够聚集最多人数的村庄作为新的教学地点.人间之里由N个村庄(编号为1..N)和M条道路组成,道路分为两种一种为单向通行的,一种为双向通行的,分别用1和2来标记.如果存在