论记忆化搜索
什 么是记忆化搜索呢?搜索的低效在于没有能够很好地处理重叠子问题;动态规划虽然比较好地处理了重叠子问题,但是在有些拓扑关系比较复杂的题目面前,又显得 无奈。记忆化搜索正是在这样的情况下产生的,它采用搜索的形式和动态规划中递推的思想将这两种方法有机地综合在一起,扬长避短,简单实用,在信息学中有着 重要的作用。用一个公式简单地说:记忆化搜索=搜索的形式+动态规划的思想。
以 上的定义是抄的,说的非常神奇。一开始啊,我也不理解。因为我是遇到某些题然后百度到的。经过学习,我发现,所谓记忆化搜索说白了就是暴力枚举。只不过略 微优雅一点,把算过的,有可能发生重复的部分进行记忆,不要发生重复计算即可。这就是所谓的记忆化搜索,这是我的理解。
在学习它的过程中,人们总要讲到什么是动态规划,讲到普通的搜索。而在看麻省理工学院公开课:计算机科学及编程导论第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 ",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 ",i+1); else printf("Data set %d: no ",i+1); } } }
第二题:UVA10003
/* * 这道题用的记忆化搜索 * 说白了就是暴力枚举,然后找出最佳结果 * 找的过程中注意使用默记法而已。。。。。 * 这道题的原型是《最佳矩阵乘法》 * 大致过程为每一步寻找一个最佳中位点,然后递归的找 * 出来的结果是最终结果 * 核心是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. ",ans); } int main() { while(scanf("%d",&L)!=EOF && L!=0) { input(); solve(); output(); } }
其中第二题是百度的答案,我第一次碰到的记忆化搜索题。
实话说,刘汝佳的UVA题还是挺好的。