论记忆化搜索

论记忆化搜索

什么是记忆化搜索呢?搜索的低效在于没有能够很好地处理重叠子问题;动态规划虽然比较好地处理了重叠子问题,但是在有些拓扑关系比较复杂的题目面前,又显得无奈。记忆化搜索正是在这样的情况下产生的,它采用搜索的形式和动态规划中递推的思想将这两种方法有机地综合在一起,扬长避短,简单实用,在信息学中有着重要的作用。用一个公式简单地说:记忆化搜索=搜索的形式+动态规划的思想

以上的定义是抄的,说的非常神奇。一开始啊,我也不理解。因为我是遇到某些题然后百度到的。经过学习,我发现,所谓记忆化搜索说白了就是暴力枚举。只不过略微优雅一点,把算过的,有可能发生重复的部分进行记忆,不要发生重复计算即可。这就是所谓的记忆化搜索,这是我的理解。

在学习它的过程中,人们总要讲到什么是动态规划,讲到普通的搜索。而在看麻省理工学院公开课:计算机科学及编程导论第13集的时候(http://v.163.com/movie/2010/6/8/1/M6TCSIN1U_M6TCT9E81.html),讲的动态规划引言就是一个默记法(记忆化搜索)。

好了说了这么多,我们看题吧:

第一题:HDU 1501(http://acm.hdu.edu.cn/showproblem.php?pid=1501)

/*
 * 此题使用记忆化搜索
 * 事实证明,有的时候你觉得不可能重复的地方
 * 在经过大型扩展之后,会重复的非常厉害!需要自己作出判断
 * 最后在说:所谓记忆化搜索,就是暴力枚举。。。。。
 */
 
#include<stdio.h>
#include<string.h>
 
char s1[1000],s2[1000],s3[1000];
int a[201][201];//记忆化搜索,存储该状态是否检索过
int len1,len2,len3;
 
int dp(int i, int j, int k)
{
    //printf("%d%d %d\n",i,j,k);
    if(a[i][j]!=-1)
        return a[i][j];
    a[i][j] = 0;
    if(k>=len3)
        return 1;
    elseif(i<len1&&j<len2&&s1[i]==s3[k]&&s2[j]==s3[k])
        return a[i][j]= dp(i+1,j,k+1)+dp(i,j+1,k+1);
    elseif(i<len1&&s1[i]==s3[k])
        return a[i][j]= dp(i+1,j,k+1);
    elseif(j<len2&&s2[j]==s3[k])
        return a[i][j]= dp(i,j+1,k+1);
    else
        return a[i][j]= 0;
}
 
int main()
{
    int n;
   while(scanf("%d",&n)!=EOF)
    {
        int i;
       for(i=0;i<n;i++)
        {
           memset(a,-1,sizeof(a));
           scanf("%s%s%s",s1,s2,s3);
            len1 =strlen(s1);
            len2 =strlen(s2);
            len3 =strlen(s3);
           if(dp(0,0,0)>0)
               printf("Data set %d: yes\n",i+1);
            else
               printf("Data set %d: no\n",i+1);
        }
    }
 
}

第二题:UVA10003

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=114&page=show_problem&problem=944


/*
 * 这道题用的记忆化搜索
 * 说白了就是暴力枚举,然后找出最佳结果
 * 找的过程中注意使用默记法而已。。。。。
 * 这道题的原型是《最佳矩阵乘法》
 * 大致过程为每一步寻找一个最佳中位点,然后递归的找
 * 出来的结果是最终结果
 * 核心是dp函数
 */
#include<stdio.h>
#include<string.h>
#define MAX 0x7fffffff
int f[60][60],L,N,ans,c[60];
void input()
{
     scanf("%d",&N);
      int t;
      c[0]=0;
      c[N+1]=L;
      for(inti=1;i<=N;i++)
      {
         scanf("%d",&c[i]);
      }
}
int dp(int i,int j)
{
    if(f[i][j]!=-1)
        return f[i][j];
    else if(i==j-1)
        returnf[i][j]=0;
    else {
        f[i][j]=MAX;
        int t;
        for(intk=i+1;k<j;k++)
        {
          t=dp(i,k)+dp(k,j)+c[j]-c[i];
          if(f[i][j]>t)
             f[i][j]=t;
        }
        return f[i][j];
    }
}
void solve()
{
   memset(f,-1,sizeof(f));
    ans=dp(0,N+1);
}
void output()
{
    printf("Theminimum cutting is %d.\n",ans);
}
int main()
{
   while(scanf("%d",&L)!=EOF && L!=0)
    {
        input();
        solve();
        output();
    }
 
}

其中第二题是百度的答案,我第一次碰到的记忆化搜索题。

实话说,刘汝佳的UVA题还是挺好的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值