结合滑雪讨论DFS和记忆化搜索问题

2021-04-18   00:22:38

DFS(深度优先搜索):

关于DFS的定义概念介绍参看:深度优先搜索

简单来说,DFS可以理解为深度优先的递归加回溯。

下面看题:洛谷P1434

题目描述

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

一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度会减小。在上面的例子中,一条可行的滑坡为 2417-16-1(从 24 开始,在 1 结束)。当然 25-24-23-\ldots…-3-2-1 更长。事实上,这是最长的一条。

输入格式

输入的第一行为表示区域的二维数组的行数 RR 和列数 CC。下面是 RR 行,每行有 CC 个数,代表高度(两个数字之间用 11 个空格间隔)。

输出格式

输出区域中最长滑坡的长度。

输入输出样例

输入 #1
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
输出 #1
25

说明/提示

对于 100\%100% 的数据,1\leq R,C\leq 1001R,C100。

第一思路:

首先想到枚举每一个点的可能最长路径,在这里需要用到DFS,故可写出dfs函数如下:

int dfs(int x, int y)
{
    int ans2 = 0;
    for (int i = 0; i < 4; i++)
    {
        int q = x + dic[i][0];//dic为方向变量控制上下左右
        int t = y + dic[i][1];
        if (q >= 0 && t >= 0 && q < R && t < C && a[q][t] < a[x][y])
        {
            ans2 = max(ans2, dfs(q, t));
        }
    }

    return ans2+1;
}    

    但食用后发现会TLE,这是因为每一个点可能被重复多次循环记录到,每一次for循环都会重复计算,而如果能设置一个变量使之直接表示该点所能达到的最长路径,就可以省去许多时间。这就有了第二种思路,记忆化搜索.

第二思路:

记忆化搜索:记忆化搜索的思想是,在搜索过程中,会有很多重复计算,如果我们能记录一些状态的答案,就可以减少重复搜索量

因此我们设置一个二维数组dp[x][y]来表示在点(x,y)处所能达到的最长路径。

代码如下:

int dfs(int x, int y)
{
    if (dp[x][y]) return dp[x][y];//如果dp不为0,证明该点已经被计算过了,直接返回该点的值即可。
    dp[x][y] = 1;//某个点最短也是1,为了和0区分判断是否被计算过
    for (int i = 0; i < 4; i++)
    {
        int q = x + dic[i][0];
        int t = y + dic[i][1];
        if (q >= 0 && t >= 0 && q < R & t < C && a[q][t] < a[x][y])
        {
            dfs(q, t);
            dp[x][y] = max(dp[x][y], dp[q][t] + 1);
        }
    }
    return dp[x][y];
}

主函数部分:

int main()
{
    cin >> R >> C;
    for (int i = 0; i < R; i++)
    {
        for (int j = 0; j < C; j++)
        {
            cin >> a[i][j];
        }
    }
    for (int x = 0; x < R; x++)
    {
        for (int y = 0; y < C; y++)
        {
            ans = max(ans, dfs(x, y));
        }
    }
    cout << ans;
    return 0;
}

未完待续,后续仍会补充......

posted @ 2021-04-18 00:24  黯战丿风魂  阅读(182)  评论(0)    收藏  举报