滑雪问题

题目转自CSDN博客,是一道很经典的DP题目,从这道题目,我可以学到两点:
1.动态规划,在递归下的记忆化搜索算法;
2.状态转移方程的推导;
题目描述如下:
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
#include   
  
using namespace std;  
//全局记录  
int points[ 100 ][ 100 ];  
int maxlen[ 100 ][ 100 ] = { 0 };  
int row ,col;  
  
//DP的函数  
int DP( int i, int j )  
  
{  
  
      int max = 0;  
      //检查该点是否已经处理过(原来数组里都初始化为0,处理过的数据大于0,记忆化搜索的方法)  
      if ( maxlen[ i ][ j ] )   
           return maxlen[ i ][ j ];  
  
      //递归记录下每个点的最长长度  
  
      //向上  
  
      if ( j > 0 && points[ i ][ j ] > points[ i ][ j - 1 ] && max < DP( i, j - 1 ) )  //三个判断分别是:防止越界&& 高度比较&& 是否最优,下同  
           max = DP( i, j - 1 );  
      //向下  
      if (j < col - 1 && points[ i ][ j ] > points[ i ][ j + 1 ] && max < DP( i, j + 1 ) )  
           max = DP( i, j + 1 );  
      //向左  
      if ( i > 0 && points[ i ][ j ] > points[ i - 1 ][ j ] && max < DP( i - 1, j ) )  
           max = DP( i - 1, j );  
      //向右  
      if ( i < row - 1 && points[ i ][ j ] > points[ i + 1 ][ j ] && max < DP( i + 1, j ) )  
           max = DP( i + 1, j );  
      //搜索完成后记录结果,如果四个方向都没有符合的点,则max仍然为,结果是;  
      maxlen[ i ][ j ] = max + 1;  
      //返回  
      return maxlen[ i ][ j ];  
}  
int main()  
  
{   
      int i, j, max = 0;  
      cin >> row >> col;  
      //读入  
      for ( i = 0; i < row; i ++ )  
           for ( j = 0; j < col; j ++ )  
                 cin >> points[ i ][ j ];  
      //逐个点处理  
      for ( i = 0; i < row; i ++ )  
           for ( j = 0; j < col; j ++ )  
                 DP( i, j );  
  
      //寻找最大值  
  
      for (i = 0; i < row; i ++ )  
           for ( j = 0; j < col; j ++ )  
                 if ( max < maxlen[ i ][ j ] )  
                      max = maxlen[ i ][ j ];  
      cout << max << endl;  
    return 0;  
} 

这道题目是求最长下降子序列在二维面上的一个扩展问题,它的简单版本是求一维最长下降(上升)子序列,可以认为是DP算法的入门级题目。

记忆化搜索算法并不高深,就是对已经操作的数据用时间换取空间的做法,做个记录下次运算到时能快...

你可能感兴趣的:(数据结构与算法)