关于记忆化搜索

1.记忆化搜索的思想

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

2、记忆化搜索的适用范围

    根据记忆化搜索的思想,它是解决重复计算,而不是重复生成,也就是说,这些搜索必须是在搜索扩展路径的过程中分步计算的题目,也就是“搜索答案与路径相关”的题目,而不能是搜索一个路径之后才能进行计算的题目,必须要分步计算,并且搜索过程中,一个搜索结果必须可以建立在同类型问题的结果上,也就是类似于动态规划解决的那种。

也就是说,他的问题表达,不是单纯生成一个走步方案,而是生成一个走步方案的代价等,也就是说由于利益关系,走到(x,y)点后你必须往(a,b)点走才可以得到最大利益,因此,每一次经过(x,y)点,都会向(a,b)点走,所以我们可以直接将(x,y)点的状态记录一下,然后直接回溯就可以。

3、记忆化搜索的核心实现

     a. 首先,要通过一个表记录已经存储下的搜索结果,一般用二维数组。

     b. 在每一状态搜索的开始,如果这个位置已经访问过了,直接调用答案,回溯

    c .如果没有,则按正常方法搜索

4、记忆化搜索是类似于动态规划的,不同的是,它是倒做的“递归式动态规划”。

例题:

Glory非常喜欢玩滑滑梯游戏,下面给出了一个n,m的滑道,其中的数字表示滑道的高度。Glory可以从一个点出发向下滑行,每次只能滑行到相邻的位置(上下左右)中高度严格低于当前高度的地方,不能重复划行已经滑行过的地方,但他希望在这个滑道上滑行尽量远的距离,也即是找一条最长的滑道。

Input

第一行输入两个数n,m代表滑梯范围行n和列m(1 <= n,m <= 100)。下面是n行,每行有m个整数,代表高度h,(0<=h<=20000)

Output

输出一个值,代表Glory能够在滑滑梯上面滑行的最长长度是多少

Sample Input

3 3
9 1 2
5 6 7
8 4 3

Sample Output

4

Sample Input

4 7
7 6 5 4 3 2 1
1 5 1 1 1 1 1
1 4 3 1 1 1 1
1 5 6 7 8 1 1

Sample Output

7

hint

样例1:7->6->4->3 长度为4

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m;
int mp[100+10][100+10];
int dp[100+10][100+10];
int d[4][2]={{1,0},{0,1},{0,-1},{-1,0}};
//每次都是以一个点为单位,判断是否搜索过,如果没有的话,往下走,,判断满足条件的下一个点是否搜索
//过,直到下一个点搜索过,或者无路可走,就开始返回了,最先返回的应该是无路可走的那个的maxlen=1;
//(因为当前位置也算一个长度),返回到上一步以后更新len与maxle,如果继续返回的话返回的是已经更新过的
//maxlen并用dp数组记录一下。所以说dp数组的更新是倒着来的,每次都要记录当前位置的权值(maxlen=1); 
int dfs(int x,int y){
    int maxlen=1,len;
    if(dp[x][y]) return dp[x][y];
    for(int i=0;i<4;i++){
        int dx=x+d[i][0];
        int dy=y+d[i][1];
        if(dx>=1&& dy>=1&&dx<=n&&dy<=m&&mp[dx][dy]<mp[x][y]){
            len = dfs(dx,dy)+1;
            maxlen=max(len,maxlen);
        }
    }
//    cout<<x<<"++"<<y<<"_"<<maxlen<<endl;
    return dp[x][y]=maxlen;
}
int main(){
    memset(dp,0,sizeof(dp));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++){
            scanf("%d",&mp[i][j]);
        }
    }
    
    int ans=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            
            dp[i][j]=dfs(i,j);
//            cout<<i<<"+"<<j<<"_"<<dp[i][j]<<endl;
            ans=max(ans,dp[i][j]);
        }
    }
    cout<<ans<<endl;
    return 0;
}

 

转载于:https://www.cnblogs.com/Accepting/p/11269572.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值