题意:矩形滑雪区域中有各个点的高度,规定只能从高处滑向地处,问最长的滑行路线长度。
![](https://img-my.csdn.net/uploads/201302/02/1359811466_9246.jpg)
比如上面的区域最长路线为 25-24-23-...-3-2-1,长度为25,故应输出25。
解法一: DFS + 记忆化搜索
#include<string>
#include<iostream>
using namespace std;
#define MAX 100
int arr[MAX + 5][MAX + 5];
int length[MAX + 5][MAX + 5];
int r, c;
/返回四个数中的最大值
int max( int a, int b, int c, int d ){
if( a < b )
a = b;
if( c < d )
c = d;
if( a < c )
a = c;
return a;
}
///记忆化深搜
///a,b 标识二维数组元素的position
int DFS( int a, int b ){艘
搜索结束条件
if( a < 0 || b < 0 )
return 0;
已搜索过的直接取数组中的值
if( length[a][b] != 0 )
return length[a][b];
依次计算上下左右四个方向的最长路线
int x1 = 0, x2 = 0, x3 = 0, x4 = 0;
if( a + 1 < r && arr[a + 1][b] < arr[a][b] )
x1 = DFS( a + 1, b );
if( b + 1 < c && arr[a][b + 1] < arr[a][b] )
x2 = DFS( a, b + 1 );
if( a > 0 && arr[a - 1][b] < arr[a][b] )
x3 = DFS( a - 1, b );
if( b > 0 && arr[a][b - 1] < arr[a][b] )
x4 = DFS( a, b - 1 );
返回四个方向中最长路线中最大的,并+1
length[a][b] = 1 + max( x1, x2, x3, x4 );
return length[a][b];
}
int main(){
int i,j;
scanf( "%d%d" ,&r,&c );
for( i = 0; i < r; i ++ ){
for( j = 0; j < c; j ++ ){
scanf( "%d", &arr[i][j] );
}
}
int max = 0;
for( i = 0; i < r; i ++ ){
for( j = 0; j < c; j ++ ){
int a = DFS( i, j );
if( max < a )
max = a;
}
}
printf( "%d\n", max );
return 0;
}
解法二:贪心
按高度从高到低对各个点排序,然后依次计算到该点为止的最长线路。
#include<string>
#include<iostream>
#include<queue>
using namespace std;
#define MAX 100
int arr[MAX + 5][MAX + 5];
int length[MAX + 5][MAX + 5];
int r, c;
struct NODE{ int x,y;}; /各个点
int dir[8] = {0,1,0,-1,1,0,-1,0}; /方向数组
优先级队列中的比较符
bool operator < ( NODE a, NODE b ){
return arr[a.x][a.y] < arr[b.x][b.y];
}
///检查是否未出矩形边界
bool check( int x, int y ){
return x >= 0 && x < r && y >=0 && y < c;
}
//返回a与b中较大者
int getMax( int a, int b ){
if( a < b )
return b;
return a;
}
int main(){
int i,j;
NODE node;
~scanf( "%d%d" ,&r,&c );
priority_queue<NODE> q;
for( i = 0; i < r; i ++ ){
for( j = 0; j < c; j ++ ){
scanf( "%d", &arr[i][j] );
node.x = i;
node.y = j;
q.push( node ); /各个点按照高度进入优先级队列,最大者会先出队
}
}
while( !q.empty() )
{
node = q.top();
q.pop();
int k;
int x = node.x;
int y = node.y;
返回当前点的上下左右四个方向中比其高度高的点中滑行路线最长的
for( k = 0; k < 8; k += 2 ){
if( check( x + dir[k], y + dir[k + 1])){
if( arr[x + dir[k]][y + dir[k + 1]] > arr[x][y] ){
length[x][y] = getMax( 1 + length[x + dir[k]][y + dir[k + 1]], length[x][y] );
}
}
}
}
int max = 0;
for( i = 0; i < r; i ++ ){
for( j = 0; j < c; j ++ ){
if( max < length[i][j] )
max = length[i][j];
}
}
printf( "%d\n", 1 + max );
return 0;
}