洛谷[P1434 [SHOI2002]滑雪] {动态规划的引入}|{dfs} 奋斗的珂珂~

洛谷[P1434 [SHOI2002]滑雪] {动态规划的引入}|{dfs}

题目描述

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(从24 开始,在 1 结束)。当然 25-24-23-…-3-2-1更长。事实上,这是最长的一条。

输入格式

输入的第一行为表示区域的二维数组的行数 R 和列数 C。下面是 R 行,每行有 C 个数,代表高度(两个数字之间用 1 个空格间隔)。

输出格式

输出区域中最长滑坡的长度。

输入输出样例

输入
5 5
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
输出
25

说明/提示

对于 100% 的数据,1≤R,C≤100。

解题思路

1、dfs深度优先搜索,对当前的点进行深度优先搜索,可以走的是周围的四个点,再进行搜索,直到周围点的高度都比当前点的高度高,或者周围的点已经不在矩阵范围之内(r,c之内),就返回dp的值。

2、记忆化,如果直接dfs那么会超时,所以需要对处理之后的进行标记处理,也就是说如果搜索到的点已经处理过**(dp[i][j]的值不为0),那么就直接返回dp[i][j]的值**。如果dp[i][j]的值为0(初始时就为0),那么说明没处理过,所以先令它为1(因为这个点一定走)。

注意

1、本题求解的是经过的点的个数,而不是长度!!!

2、dfs(x,y)+1表示的是走向这一点所以长度需要+1。dp需要取能走长度的最大值。
       dp[p][q]=max(dfs(x,y)+1,dp[p][q]);

完整代码

#include
using namespace std;
int a[110][110];
int dp[110][110];
int b[4][2]={{1,0},{0,-1},{-1,0},{0,1}};//代表周围四个坐标进行操作的转移位置的数值 
int r,c;

int dfs(int p,int q)
{
	if(dp[p][q]) return dp[p][q];//如果已经进行寻找过,就直接返回当前dp的值 ,利用记忆化 
	dp[p][q]=1;//如果没有查找过,就设置当前长度至少为1 
	for(int i=0;i<4;i++)
	{
		int x=p+b[i][0];
		int y=q+b[i][1];
		if(x>=1&&x<=r&&y>=1&&y<=c&&a[x][y]<a[p][q])//如果满足其坐标还在当前区域内并且高度小于当前高度 
		{                                          //此时说明可以下滑 
			dp[p][q]=max(dfs(x,y)+1,dp[p][q]);//dp就表示从a[i][j]滑到下一高度的最大长度(最多可以走几下) 
		}
	}
	return dp[p][q];
}

int main()
{
	scanf("%d %d",&r,&c);
	for(int i=1;i<=r;i++)
	{
		for(int j=1;j<=c;j++)
		{
			scanf("%d",&a[i][j]);
		}
	}
	int ans=0;
	for(int i=1;i<=r;i++)
	{
		for(int j=1;j<=c;j++)
		{
			ans=max(ans,dfs(i,j));//比较当前坐标下的点可以走的长度与之前的最长的长度的值 
		}
	}
	printf("%d",ans);
	return 0;
 } 

你可能感兴趣的:(动态规划的引入)