Algorithm8.3 DFS 记忆化搜索

[TOC]

DFS 记忆化搜索

用于相邻依赖 => 涂色:相邻的不能相同;连续递增/连续递减

搜索的形式+dp的存储思想,把dp数组融合到dfs搜索的过程中。

[模版] 记忆化搜索 - 优化重复递归调用

https://www.luogu.com.cn/problem/P1464

题目大意:纯粹的重复递归调用,极限的话20 * 20 * 20次不同的计算要被一直算,如果可以记录下来,那么这么多次运算只需要算一遍。

1、用dp来记录下来每次的递归结果,也就是return之前先给dp附上值。return dp=w();

2、注意return的时候,看看边界条件,特判条件放在前面先return;递归条件放后面return

#include <iostream>
using namespace std;
#define maxn 25
typedef long long ll;
ll ta, tb, tc, dp[maxn][maxn][maxn];

ll dfs(int a, int b, int c) {
    if (a <= 0 || b <= 0 || c <= 0) return 1;
    if (a > 20 || b > 20 || c > 20) return dfs(20, 20, 20);
    if (dp[a][b][c])  return dp[a][b][c];
    if (a < b && b < c) return dp[a][b][c] = dfs(a, b, c-1) + dfs(a, b-1, c-1) - dfs(a, b-1, c);
    else return dp[a][b][c] = dfs(a-1, b, c) + dfs(a-1, b-1, c) + dfs(a-1, b, c-1) - dfs(a-1, b-1, c-1);
}

int main() {
    while (scanf("%lld%lld%lld", &ta, &tb, &tc) && !(ta==-1 && tb==-1 && tc==-1))
      printf("w(%lld, %lld, %lld) = %lld\n", ta, tb, tc, dfs(ta, tb, tc));
    return 0;
}

记忆化搜索

https://www.luogu.com.cn/problem/P1434

题目大意:地图中最长的路线,没有固定起点。

1、没有固定起点,就代表要所有点都做起点去算一遍。所以计算的总成本就是算一个点的成本*总共的点数=>多次重复计算,所以用记忆化搜索来储存减少运算量

2、先递归满足往深层次拓展的点,然后拓展完成之后,再来更新dp数组。dfs(nx, ny);然后dp[x][y] = max(dp[x][y], dp[nx][ny]+1);

#include <iostream>
using namespace std;
#define maxn 205
int r, c, mp[maxn][maxn], dp[maxn][maxn], ans, dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; // dp[i][j]这个点开始的最长连续下降的长度

int dfs(int x, int y) {
    if (dp[x][y]) return dp[x][y];
    dp[x][y] = 1;
    for (int i = 0; i < 4; ++i) {
        int nx = x+dir[i][0], ny = y+dir[i][1];
        if (nx >= 0 && nx < r && ny >= 0 && ny < c && mp[nx][ny] < mp[x][y]){
            dfs(nx, ny);
            dp[x][y] = max(dp[x][y], dp[nx][ny]+1);
        }
    }
    return dp[x][y];
}

int main() {
    scanf("%d%d", &r, &c);
    for (int i = 0; i < r; ++i)
        for (int j = 0; j < c; ++j)
            scanf("%d", &mp[i][j]);
    for (int i = 0; i < r; ++i)
        for (int j = 0; j < c; ++j)
            ans = max(ans, dfs(i, j));
    printf("%d\n", ans);
    return 0;
}
Posted on Feb 1, 2021