题目链接: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;
}