博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
hdoj1078(介绍记忆化搜索及其模板)
阅读量:6284 次
发布时间:2019-06-22

本文共 1479 字,大约阅读时间需要 4 分钟。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1078

思路:

这是一道典型的记忆化搜索模板题。

先介绍记忆化搜索,本质是搜索+DP。

一般说来,动态规划总要遍历所有的状态,而搜索可以排除一些无效状态。更重要的是搜索还可以剪枝,可能剪去大量不必要的状态,因此在空间开销上往往比动态规划要低很多。记忆化算法在求解的时候还是按着自顶向下的顺序,但是每求解一个状态,就将它的解保存下来,以后再次遇到这个状态的时候,就不必重新求解了。这种方法综合了搜索和动态规划两方面的优点,因而还是很有实用价值的。

记忆化搜索(Memory Search),其实还是用递归函数实现的,通常函数名依然叫做dfs。核心语句就是那两部分关键的语句块:

        1.函数一开始的判断出口:if(搜索过) return 数组中的值。因为这里涉及到是否搜索过,所以一般将数组初始化为-1。
        2.函数的递归前进语句:return fib[i]=fib[i-1]+fib[i-2];(没有具体的例子实在不好说了,所以这里用fib数列来做演示)。
这样就做到了数组的每个值只计算了一次,不会有多余的时间消耗。

下面就这道题来讲记忆化搜索基本模板,用dp[i][j]表示从(i,j)出发吃到的cheese最多的值,用(x,y)表示其邻点,则:

dp[i][j]=max(dp[i][j],a[i][j]+dp[x][y])(满足a[x][y]>a[i][j]时)。在这个递推式中,如果dp[i][j]被计算过一次,其值就是最终值,不用再计算。但是如果使用一般的dfs,则会出现大量重复计算一个值的情况,必然会超时。所以采用记忆化搜索,在递推过程中如果一个值被计算过(>=0),直接返回即可,否则计算其最终值并赋给它。也可以使用DP做这道题,但是要先排序,按照顺序来DP,但比较麻烦。而记忆化搜索则简洁自然许多,其实质当然就是DP。

详见代码:

1 #include
2 using namespace std; 3 4 int n,k; 5 int a[105][105],dp[105][105]; 6 int go[4][2]={-1,0,0,1,1,0,0,-1}; 7 8 int dfs(int x,int y){ 9 if(dp[x][y]>=0) return dp[x][y];10 dp[x][y]=a[x][y];11 for(int i=0;i<4;++i)12 for(int j=1;j<=k;++j){13 int xx=x+j*go[i][0],yy=y+j*go[i][1];14 if(xx>=0&&xx
=0&&yy
a[x][y])15 dp[x][y]=max(dfs(xx,yy)+a[x][y],dp[x][y]);16 }17 return dp[x][y];18 }19 20 int main(){21 while(~scanf("%d%d",&n,&k)&&n!=-1){22 for(int i=0;i

 

转载于:https://www.cnblogs.com/FrankChen831X/p/10434649.html

你可能感兴趣的文章
LINK2005 error
查看>>
艾伟_转载:ASP.NET缓存
查看>>
Gnome Tweak Tool 3.0.5发布
查看>>
CentOS6.5安装Tomcat8.0
查看>>
T-sql 递归构造连续日期序列
查看>>
C++循环语句
查看>>
[文摘20111215]急事慢慢说
查看>>
做完c++课程设计感想(悔恨)
查看>>
安装vi
查看>>
win7下vs2008编译出现C1859错误的处理办法
查看>>
8个方法让你成为更优秀的程序员
查看>>
JS——简单的正则表达式验证
查看>>
RP2833 FPGA对应串口标识
查看>>
avalon2学习教程02之vm
查看>>
注意字符串换行链接的格式
查看>>
android开发之自定义圆形ImagView
查看>>
Alley Bird 跳跳鸟源码
查看>>
AJAX技术入门 第一节 走进AJAX
查看>>
开源库FANN学习笔记1
查看>>
msys
查看>>