滑雪滑雪 滑 雪
题目大意:
有一个N*M的矩阵,每个位置都有一个数,可以从大的数走向小的数,问可走的路最长是多少
原题
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
一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-…-3-2-1更长。事实上,这是最长的一条(如下)。
Input
输入的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。
Output
输出最长区域的长度。
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
方法一
用递归的方法,从每一个位置开始都试一遍,就可以TLE了 ,一定要用记忆化搜索!保存每一位的最优值,速度会快很多,就AC了
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int n, m, a[ 505 ] [ 505 ] , f[ 505 ] [ 505 ] , sum;
const int dx[ 4 ] = { 1 , 0 , - 1 , 0 } ;
const int dy[ 4 ] = { 0 , 1 , 0 , - 1 } ;
int js ( int x, int y)
{ if ( f[ x] [ y] ) return f[ x] [ y] ; f[ x] [ y] = 1 ; for ( int k= 0 ; k< 4 ; k++ ) if ( ( x+ dx[ k] > 0 ) && ( x+ dx[ k] <= n) && ( y+ dy[ k] > 0 ) && ( y+ dy[ k] <= m) && ( a[ x] [ y] > a[ x+ dx[ k] ] [ y+ dy[ k] ] ) ) f[ x] [ y] = max ( f[ x] [ y] , js ( x+ dx[ k] , y+ dy[ k] ) + 1 ) ; return f[ x] [ y] ;
}
int main ( )
{ scanf ( "%d%d" , & n, & m) ; for ( int i= 1 ; i<= n; i++ ) for ( int j= 1 ; j<= m; j++ ) scanf ( "%d" , & a[ i] [ j] ) ; for ( int i= 1 ; i<= n; i++ ) for ( int j= 1 ; j<= m; j++ ) sum= max ( sum, js ( i, j) ) ; printf ( "%d" , sum) ; return 0 ;
}
方法二
用线性DP的方法,先把每一位用一个数组a存起来,在按高度从小到大排序,从小到大每一次都判断是否能往四周走,能就是下一步+1,求max,用f[i][j]记从i,j开始的最长长度,
#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
const int dx[ 4 ] = { 1 , 0 , - 1 , 0 } ;
const int dy[ 4 ] = { 0 , 1 , 0 , - 1 } ;
int n, m, t, ans, f[ 505 ] [ 505 ] , b[ 505 ] [ 505 ] , x1, x2, y1, y2;
struct rec
{ int x, y, h;
} a[ 250005 ] ;
bool cmp ( rec ai, rec bi)
{ return ai. h< bi. h;
}
int main ( )
{ scanf ( "%d%d" , & n, & m) ; for ( int i= 1 ; i<= n; i++ ) for ( int j= 1 ; j<= m; j++ ) { t++ ; scanf ( "%d" , & b[ i] [ j] ) ; a[ t] . x= i; a[ t] . y= j; a[ t] . h= b[ i] [ j] ; f[ i] [ j] = 1 ; } sort ( a+ 1 , a+ 1 + t, cmp) ; for ( int i= 1 ; i<= t; i++ ) { x1= a[ i] . x; y1= a[ i] . y; for ( int k= 0 ; k< 4 ; k++ ) { x2= x1+ dx[ k] ; y2= y1+ dy[ k] ; if ( ( x2> 0 ) && ( x2<= n) && ( y2> 0 ) && ( y2<= m) && ( b[ x1] [ y1] > b[ x2] [ y2] ) ) f[ x1] [ y1] = max ( f[ x1] [ y1] , f[ x2] [ y2] + 1 ) ; } ans= max ( f[ x1] [ y1] , ans) ; } printf ( "%d" , ans) ; return 0 ;
}