首先的首先,必须明白动态规划(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.