POJ 1088.滑雪

这个题本来是DP的,但是自己不太会,根据网上的代码学习以后发现dfs的方式自己更好理解,主要在于dfs函数的代码

find(x,y)的返回值代表这个位置的已知最大连续值,这样在递归时直接就可以理解成那个位置的最大连续值,从而直接使用

题目链接

/*
	滑雪 百练POJ1088 要求不断的单调递减  通过这个题发现很多DP问题都在于记忆化遍历
	 一定要记住一个东西 且记住的东西一般等于max(a,b) 
	输出最长区域的长度
	
	并且能找到一个边界问题 即所有点里最低的点是边界已知的l值是1 
	这个题值得训练 
*/
#include <iostream>
#include <algorithm> 
using namespace std;
int a[105][105];//输入存储 
int l[105][105] = {0};//记忆 表示从点i  j 出发的最长滑行长度 
int r,c;//依次是行数 列数run a,run b)

int dx[4] = {1,0,-1,0};
int dy[4] = {0,1,0,-1};
int find(int x,int y)
{
	if(l[x][y]!=0) //记忆化剪枝 如果这个位置已经有值了 
	{
		return l[x][y];
	}
	l[x][y] = 1; 
	for(int i=0;i<4;i++)//四个方向遍历dfs 
	{
		int tx = x + dx[i];
		int ty = y + dy[i]; 
		if(tx>=0&&tx<r&&ty>=0&&ty<c&&a[x][y]>a[tx][ty])
		{
			l[x][y] = max(l[x][y],find(tx,ty)+1);//这里在不断改变着lxy的值 
			//这个位置的最大值 等于当前的值和 周围四个值+1比较 周围的find 只有比当前大才继续find 
		}
	}
	return l[x][y]; 
}
int main(void)
{
	int count = 0;
	scanf("%d%d",&r,&c); 
	for(int i=0;i<r;i++)
	{
		for(int j=0;j<c;j++)
		{
			scanf("%d",&a[i][j]);
		}	
	}
	int m = 1;
	for(int i=0;i<r;i++)
	{
		for(int j=0;j<c;j++)
		{
			m = max(m,find(i,j));	
		}	
	}	
	printf("%d\n",m);
}
//DP &DFS

猜你喜欢

转载自blog.csdn.net/curiousliu/article/details/81192670