动态规划经典题目——滑雪问题(递归+记忆化搜索)

一、题目

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更长。事实上,这是最长的一条。

二、解题思路

动态规划解题思路可详见另一篇文章。

  1. 设二维数组dp[i][j]表示从(i,j)滑到低坡的最大长度。
  2. 解题技巧:在矩阵周围加入数值为正无穷大数值(INT_MAX);
  3. If exist a[i][j] > a[i-1][j] or  a[i][j] > a[i][j-1]  or  a[i][j] > a[i+1][j] or a[i][j] >  a[i][j+1]                                                                          dp[i][j] = max(  dp[i-1][j] , dp[i][j-1] , dp[i+1][j] , dp[i][j+1]) + 1;                                                                                          else                                                                                                                                                                                             dp[i][j] = 1 ;

三、代码编写

#include 
#include 
#include 

#define N 7
#define max(a,b) ((a>b)?a:b)

//定义四个方向,上、左、下、右
int dir[4][2] ={{-1,0},{0,-1},{1,0},{0,1}};
//保存最大长度
int maxRuslt = 0;
//定义矩阵
int a[N][N]={{INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX},
                 {INT_MAX,1,2,3,4,5,INT_MAX},
                 {INT_MAX,16,17,18,19,6,INT_MAX},
                 {INT_MAX,15,24,25,20,7,INT_MAX},
                 {INT_MAX,14,23,22,21,8,INT_MAX},
                 {INT_MAX,13,12,11,10,9,INT_MAX},
                 {INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX}};
//定义dp
int dp[N][N] = {0};

int dfs(int i,int j){

    //递归出口
    if((a[i][j] < a[i-1][j]) && (a[i][j] < a[i][j-1]) && (a[i][j] < a[i+1][j]) && (a[i][j] < a[i][j+1])){
        return dp[i][j] = 1;
    }
    //已经算出来则不需再计算(备忘录)
    else if(dp[i][j] > 0){
        return dp[i][j];
    }
    else{
        int k ;
        int count = 0;
        int temp = 0;
        for(k=0 ; k < 4 ;k++){
            if(a[i][j] > (a[i + dir[k][0]][j + dir[k][1]])){
                //继续递归
                temp = dfs(i + dir[k][0],j + dir[k][1]) + 1;
                count = max(count,temp);
                dp[i][j] = count;
                //最大值保存在全局变量
                maxRuslt = max(maxRuslt,count);
                //printf("temp = %d;count = %d;maxResult = %d;\n",temp,count,maxRuslt);
            }
        }
        return count;
    }
}

int main()
{
    int i,j;
    for(i =1 ; i < N-1 ; i++){
        for(j =  1 ; j < N-1 ; j++){
            dfs(i,j);
        }
    }
    printf("%d",maxRuslt);

    return 0;
}

四、运行结果

动态规划经典题目——滑雪问题(递归+记忆化搜索)_第1张图片

你可能感兴趣的:(算法)