NYOJ10——skiing

题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=10http://

分析:其实这个题目是一维的最长子序列的变形。如果是一维的,那我们访问到数组的第i个数时,它的最长递增子序列只和前一个比它小的数有关,假设这个数的下标是j,故取max(dp[i],dp[j-1] + 1)。

而这里是二维,并且第[i][j]个数是与上下左右四个方向的最长递增子序列相关的。所以这道题结合了动态规划和深度优先搜索。基于同样的思想,dp[i][j]初值设为0;每访问到一个点,它的dp[i][j]至少为1;因为至少包含自己。取max(上,下,左,右,自己),对上下左右四个方向进行深度搜索,然后更新dp[i][j]。

参考代码:

#include<stdio.h>
#include<string.h>

int dp[100][100];
int Map[100][100];
int m,n;
int d[4][2] = {{-1,0},{0,-1},{1,0},{0,1}};
inline int max(const int a, const int b)
{
	return a > b ? a : b;
}

int DSF(int x, int y)
{
	if(dp[x][y] > 0)//如果更新过了,就直接返回
		return dp[x][y];
	int tx,ty;
	dp[x][y] = 1;
	for(int i = 0; i < 4; ++i)
	{
		tx = x + d[i][0];
		ty = y + d[i][1];
		if(tx < 0 || tx >= m || ty < 0 || ty >= n)
			continue;
		if(Map[tx][ty] > Map[x][y])//满足条件,深搜,取四个方向的最大值
			dp[x][y] = max(dp[x][y], DSF(tx,ty) + 1);
	}
	return dp[x][y];
}

int main()
{
	int i,j;
	int ans;
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d %d",&m,&n);
		memset(dp,0,sizeof(dp));

		for(i = 0; i < m; ++i)
			for(j = 0; j < n; ++j)
				scanf("%d",&Map[i][j]);

		ans = 0;
		for(i = 0; i < m; ++i)
			for(j = 0; j < n; ++j)
				ans = max(ans, DSF(i,j));

		printf("%d\n",ans);
	}
	return 0;
}


你可能感兴趣的:(ACM,DFS)