POJ 1088 之二解

题目链接

题意:矩形滑雪区域中有各个点的高度,规定只能从高处滑向地处,问最长的滑行路线长度。

 

比如上面的区域最长路线为 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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值