POJ 1088 之二解

本文介绍了一种寻找滑雪路径最长距离的算法实现,通过两种不同的方法:DFS+记忆化搜索和贪心算法来解决该问题。针对给定的矩形滑雪区域地图,找到从任意高点到低点的最长滑行路线。

题目链接

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

 

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


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值