滑雪(dp+深搜)

本文介绍了一种使用记忆化搜索解决滑雪场最长滑行路径问题的方法。通过递归算法结合动态规划思想,在r行c列的矩形地图中寻找最长的连续下坡滑行路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem 35: 滑雪


Time Limit:1 Ms| Memory Limit:128 MB
Difficulty:3

Description

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

Input

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

Output

仅一行: 输出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


思路:记忆化搜索(今天刚知道原来这叫记忆化搜索), 就是深搜, 但是要将搜索过的

结果保存起来下次深搜时可直接调用(优化后的递归求斐波纳锲数列),用两个二维数

len[x][y], hight[x][y]分别表示x,y可以滑的最远步数和每个点的高度, 用递归实现动归的

从小到大求值。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 100
 
int n, m, len[MAX][MAX], hight[MAX][MAX], dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
 
int dfs(int x, int y)
{
     
    if(len[x][y] != 0)
    {
        return len[x][y];
    }
    int max = 0, t, tx, ty;                //每次搜索之前将到(x,y)的最长路径长度max赋为0
    for(int i = 0; i < 4; i++)             //搜四个方向找出最长路径
	{
        tx = x + dir[i][0];
        ty = y + dir[i][1];
        if(tx >= 0 && tx < n && ty >= 0 && ty < m && hight[tx][ty] < hight[x][y])
        {
            t = dfs(tx, ty);               //记录此方向的最长路径
            if(t > max)    
            {
                max = t;                    //刷新最长路径
            }
        }
    }
    len[x][y] = max + 1;                    //此点最长路径为max+1
    return max + 1;                         //返回此点最长路径,供上级调用
}
 
int main()
{
    int i, j, maxx;
    while(scanf("%d%d", &n, &m) != EOF)
    {
        memset(len, 0, sizeof(len));         //长度清零
        for(i = 0; i < n; i++)
        {
            for(j = 0; j < m; j++)
            {
                scanf("%d", &hight[i][j]);
            }
        }
        maxx = 0;
        for(i = 0; i < n; i++)               //遍历所有点求最长路径
        {
            for(j = 0; j < m; j++)
            {
                len[i][j] = dfs(i, j);       //调用递归函数
                if(len[i][j] > maxx)
                {
                    maxx = len[i][j];
                }
            }
        }
        printf("%d\n", maxx);                //打印最长路径
    } 
     
    return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值