Description
Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道载一个区域中最长底滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子
一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-...-3-2-1更长。事实上,这是最长的一条。
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。当然25-24-23-...-3-2-1更长。事实上,这是最长的一条。
Input
输入的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。
Output
输出最长区域的长度。
Sample Input
5 5 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
Sample Outpu
25解题思路:
记忆化搜索。程序分成两个部分,首先用memset(d,-1,sizeof(d));,把d全部初始化为-1,然后根据条件再进行递归。
在我们之前学过的搜索上更加优化,更加高级了一些,这周学的是动态规划,所以无疑还是要用到的,这就有点像DP了。
这个题目要求最高的滑度得枚举,应该每个点都需要走一遍,所以可以考虑使用dp来实现,所以可以使用d[x][y]表示从第x行y列开始滑所能下滑的高度
那么动态规划方程为d(x,y)=max{向上走,向下走,向左走,向右走}这些点的高度必须小于x行y列这个点的高度,否则无需加1了
程序代码:
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 int a[110][110],d[110][110]; 5 int m,n; 6 int c[4][2]={{1,0},{0,1},{-1,0},{0,-1}}; 7 void init() 8 { 9 int i,j; 10 for(i=0;i<m;i++) 11 for(j=0;j<n;j++) 12 scanf("%d",&a[i][j]); 13 memset(d,-1,sizeof(d)); 14 } 15 int dp(int x,int y) 16 { 17 if(d[x][y]>0) return d[x][y]; 18 d[x][y]=1; 19 for( int i=0;i<4;i++) 20 { 21 int di=x+c[i][0]; 22 int dj=y+c[i][1]; 23 if(di>=0&&di<m&&dj>=0&&dj<n&&a[di][dj]<a[x][y]&&dp(di,dj)+1>d[x][y]) 24 d[x][y]=d[di][dj]+1; 25 } 26 return d[x][y]; 27 28 } 29 int main() 30 { 31 while(scanf("%d%d",&m,&n)==2) 32 { 33 init(); 34 int i,j,sum=-1; 35 for(i=0;i<m;i++) 36 for(j=0;j<n;j++) 37 if(dp(i,j)>sum) sum=d[i][j]; 38 printf("%d ",sum); 39 } 40 return 0; 41 }