• 小谈记忆化搜索


    引言

    一般地,动态规划总要遍历全部的状态,而搜索可排除一些无效状态,特别是搜索可进行剪枝,减小空间开销。

    如何协调动态规划的高效率与高消费间的矛盾呢?

    一个折中的方法是记忆化搜索。在求解时,它依然按照自顶向下的顺序,只是每求解一个状态就将解保存,以后再遇到这种状态时,就不必重新求了。

    --《算法竞赛宝典》

    例题 洛谷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

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

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

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

     1 /*注意:本题求的是最大的高度,即走几次再+1。*/ 
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<iostream>
     5 #include<cmath>
     6 using namespace std;
     7 int n,m,ans,zx,zy;
     8 int h[500][500];
     9 int f[500][500];
    10 int dx[5]={0,0,0,1,-1};//记录上下左右走的方法,注意数组从0开始作为下标 
    11 int dy[5]={0,1,-1,0,0};
    12 int msearch(int i,int j);
    13 int main()
    14 {
    15     scanf("%d%d",&n,&m);
    16     for(int i=1;i<=n;i++)
    17     {
    18         for(int j=1;j<=m;j++)
    19         {
    20             scanf("%d",&h[i][j]);
    21         }
    22     }
    23     for(int i=1;i<=n;i++)
    24     {
    25         for(int j=1;j<=m;j++)
    26         {
    27             int t=msearch(i,j);
    28             ans=max(ans,t);//不断比较更长的高度 
    29         }
    30     }
    31     printf("%d",ans);
    32     return 0;
    33 }
    34 int msearch(int i,int j)
    35 {
    36     int t=1;
    37     if(f[i][j]>0) return f[i][j];//记忆化搜索的关键之1 
    38     for(int k=1;k<=4;k++)
    39     {
    40         zx=i+dx[k];
    41         zy=j+dy[k];
    42         if(h[zx][zy]>h[i][j]&&zx>=1&&zx<=n&&zy>=1&&zy<=m)//是否满足条件&数组防越界 
    43          t=max(msearch(zx,zy)+1,t);//t先前设成1了(起始高度为1) 
    44     }
    45     f[i][j]=t;//记忆化搜索关键之2,都搜完后记录。 
    46     return t;
    47 }

     昨日小测中的题目略微有所改动。

    题目如下:

    香穗子在田野上调蘑菇!她跳啊跳,发现自己很无聊,于是她想了一个有趣的事情,每个格子最多只能经过1次,且每个格子都有其价值

    跳的规则是这样的,香穗子可以向上下左右四个方向跳到相邻的格子,并且她只能往价值更高(这里是严格的大于)的格子跳.

    香穗子可以从任意的格子出发,在任意的格子结束,

    那么她最多能跳几次?

    本质也是记忆化搜索。另外需注意两点。

    1.问的是跳几次,不同于求高度,最后需-1;

    2.“每个格子最多只能通过1次”不需另做处理。

  • 相关阅读:
    oracle 使用正则表达式获取字符串中包含的数字
    oracle 将逗号分隔的字符串转成多行记录
    sqlplus下 查看oracle 执行计划
    使用connect by 虚拟生成100条记录
    Lomsat gelral
    Legacy
    慢慢变小的序列(好题)
    Walls(扫描线)
    线段树求面积并,面积交,周长
    最小圆覆盖(随机增量||模拟退火)
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/8589116.html
Copyright © 2020-2023  润新知