一道例题解决记忆化搜索(若干疑问)

附上代码:

#include<bits/stdc++.h>
using namespace std;
int n,m;
int f[1001][1001];
int f1[1001][1001];
int vis[1001][1001];
int dfs(int x,int y) {
    if(f1[x][y]!=0)
        return f1[x][y];
    int b=0;
    vis[x][y]=1;
    if(f[x][y]>f[x-1][y]&&x>=0&&x<n&&y>=0&&y<m&&x-1>=0&&x-1<n)
        b=max(b,dfs(x-1,y)+1);
    if(f[x][y]>f[x][y+1]&&x>=0&&x<n&&y>=0&&y<m&&y+1>=0&&y+1<m)
        b=max(b,dfs(x,y+1)+1);
    if(f[x][y]>f[x+1][y]&&x>=0&&x<n&&y>=0&&y<m&&x+1>=0&&x+1<n)
        b=max(b,dfs(x+1,y)+1);
    if(f[x][y]>f[x][y-1]&&x>=0&&x<n&&y>=0&&y<m&&y-1>=0&&y-1<m)
        b=max(b,dfs(x,y-1)+1);
    vis[x][y]=0;
    f1[x][y]=max(f1[x][y],b);
    return f1[x][y];
}

int main() {
    int i,j,sum=0;
    cin >> n >>m;
    for(i=0; i<n; i++)
        for(j=0; j<m; j++) {
            cin >> f[i][j];
            f1[i][j] = 0;
        }
    for(i=0; i<n; i++)
        for(j=0; j<m; j++)
            sum=max(sum,dfs(i,j)+1);
    cout << sum  << endl;
    return 0;
}

第一点:

f1[x][y]=max(f1[x][y],b) 这是把值储存起来,之后可以直接使用。就是以x,y为原点,下次f(x,y)会往四个方向走,取四个方向最长的长度,四个中的最大值保存起来,下次搜索的时候直接使用。

第二点:

我刚开始以为他会回溯,所以是这样搞的,避免他会回溯到原来的点。

加了一个vis[i][j]条件,防止他回溯。

另外说一点:

分别在每一个dfs函数前面加上一个vis[x][y]=1 dfs函数后面加上一个vis[x][y]=0

这两种是不同的。

第一种与第二种的区别是:

第一种只有原点的四个方向的分支都结束的时候,原点的标记才能被取消。第二种是只要一个方向的结束,标记就取消了。

后面我取消了这种标记 因为不用标记 也不会回溯到以前,因为if(f[x][y]>f[x-1][y]) 只有原点大于另外一个方向的值时候 才会调用函数。既然是大于,说明另一个方向不会回溯到原点,因为他必然小于,所以不会调用函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值