动态规划①——记忆化搜索

首先的首先,必须明白动态规划(DP)以后很有用很有用很有用很有用……
首先的其次,必须明白:动规≈搜索=枚举

一、最简单的记忆化搜索(应该可以算DP)

题目(来自洛谷OJ)http://www.luogu.org/problem/show?pid=1434#

【不麻烦大家自己找了】
题目描述 Description
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更长。事实上,这是最长的一条。
输入输出格式 Input/output
输入格式:
输入的第一行为表示区域的二维数组的行数R和列数C(1≤R,C≤100)。下面是R行,每行有C个数,代表高度(两个数字之间用1个空格间隔)。
输出格式:
输出区域中最长滑坡的长度。


很明显(经典)的搜索题目,你可以从任意一点开始搜索可以滑多远,最后找出最大值。
呵呵……时间复杂度不忍直视
所以你可以这么考虑:从一个点开始能滑的最大距离是确定不变的,所以可以用f[x,y]记录下来,并用这个数据推算出其他数据f[x-1,y],f[x+1,y],f[x,y-1],f[x,y+1]。
所以,开始吧!
AC程序:

 1 var n,m,i,j,ma:longint;a,f:array[1..100,1..100]of longint;//n m规模;i j循环变量; ma自然是最大值;a记录输入数据(地势高度);f记录从这个点开始能滑多远
 2 function max(a,b:longint):longint;begin if a>b then exit(a) else exit(b);end;//比较两数大小
 3 function find(x,y:longint):longint;//从(x,y)开始能滑多远
 4 var s:longint;
 5 begin
 6   if f[x,y]>0 then exit(f[x,y]);   //已知,直接调用
 7   s:=0;                            //未知,重新搜索
 8   if(x>1)then                                                 //上下左右找最大,别忘边界
 9   if a[x-1,y]<a[x,y] then s:=find(x-1,y);
10   if(y>1)then
11   if a[x,y-1]<a[x,y] then s:=max(s,find(x,y-1));
12   if(x<n)then
13   if a[x+1,y]<a[x,y] then s:=max(s,find(x+1,y));
14   if(y<m)then
15   if a[x,y+1]<a[x,y] then s:=max(s,find(x,y+1));
16   f[x,y]:=s+1;                    //记忆,别忘+1,否则必0
17   exit(s+1);                      //同上
18 end;
19 begin
20   readln(n,m);
21   for i:=1 to n do
22   for j:=1 to m do
23   read(a[i,j]);
24   ma:=0;
25   for i:=1 to n do
26   for j:=1 to m do
27   ma:=max(ma,find(i,j));     //看似复杂度高,其实find(1,1)后整一路的数据都已记录好,直接调用
28   writeln(ma);
29 end.
原文地址:https://www.cnblogs.com/wanglichao/p/4395826.html