一、题目
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。当然25-24-23-…-3-2-1更长。事实上,这是最长的一条。
二、解题思路
动态规划解题思路可详见另一篇文章。
- 设二维数组dp[i][j]表示从(i,j)滑到低坡的最大长度。
- 解题技巧:在矩阵周围加入数值为正无穷大数值(INT_MAX);
- If exist a[i][j] > a[i-1][j] or a[i][j] > a[i][j-1] or a[i][j] > a[i+1][j] or a[i][j] > a[i][j+1] dp[i][j] = max( dp[i-1][j] , dp[i][j-1] , dp[i+1][j] , dp[i][j+1]) + 1; else dp[i][j] = 1 ;
三、代码编写
- #include
- #include
- #include
-
- #define N 7
- #define max(a,b) ((a>b)?a:b)
-
- //定义四个方向,上、左、下、右
- int dir[4][2] ={{-1,0},{0,-1},{1,0},{0,1}};
- //保存最大长度
- int maxRuslt = 0;
- //定义矩阵
- int a[N][N]={{INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX},
- {INT_MAX,1,2,3,4,5,INT_MAX},
- {INT_MAX,16,17,18,19,6,INT_MAX},
- {INT_MAX,15,24,25,20,7,INT_MAX},
- {INT_MAX,14,23,22,21,8,INT_MAX},
- {INT_MAX,13,12,11,10,9,INT_MAX},
- {INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX}};
- //定义dp
- int dp[N][N] = {0};
-
- int dfs(int i,int j){
-
- //递归出口
- if((a[i][j] < a[i-1][j]) && (a[i][j] < a[i][j-1]) && (a[i][j] < a[i+1][j]) && (a[i][j] < a[i][j+1])){
- return dp[i][j] = 1;
- }
- //已经算出来则不需再计算(备忘录)
- else if(dp[i][j] > 0){
- return dp[i][j];
- }
- else{
- int k ;
- int count = 0;
- int temp = 0;
- for(k=0 ; k < 4 ;k++){
- if(a[i][j] > (a[i + dir[k][0]][j + dir[k][1]])){
- //继续递归
- temp = dfs(i + dir[k][0],j + dir[k][1]) + 1;
- count = max(count,temp);
- dp[i][j] = count;
- //最大值保存在全局变量
- maxRuslt = max(maxRuslt,count);
- //printf("temp = %d;count = %d;maxResult = %d;\n",temp,count,maxRuslt);
- }
- }
- return count;
- }
- }
-
- int main()
- {
- int i,j;
- for(i =1 ; i < N-1 ; i++){
- for(j = 1 ; j < N-1 ; j++){
- dfs(i,j);
- }
- }
- printf("%d",maxRuslt);
-
- return 0;
- }
'运行
评论记录:
回复评论: