解题思路:
一开始想到的就是dfs+记忆化。做完之后发现还有dp的方法。
Dp即按高度从小到大排,然后从小的点开始,每次判断
dp[tx][ty]=max(dp[tx][ty],dp[x][y]+1); //(tx,ty)是当前点(x,y)相邻四个方向的点
代码(dfs):
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
int r, c;
int f[102][102], a[102][102];
int tx[] = { 1, 0, -1, 0 };
int ty[] = { 0, 1, 0, -1 };
bool check(int x, int y)
{
return (x >= 0 && y >= 0 && x<r && y<c);
}
int dfs(int x, int y)
{
int mx, my;
int i;
int maxx = 0;
if (f[x][y])
return f[x][y];
for (i = 0; i<4; i++)
{
mx = x + tx[i];
my = y + ty[i];
if (check(mx, my) && a[x][y]>a[mx][my])
{
maxx = max(maxx, 1 + dfs(mx, my));
}
}
return maxx;
}
int main()
{
int n;
scanf("%d", &n);
while (n--)
{
memset(f, 0, sizeof(f));
int i, j;
char s[105];
scanf("%s%d%d", &s, &r, &c);
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
scanf("%d", &a[i][j]);
int mx = 0;
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
{
if (f[i][j] == 0)
f[i][j] = dfs(i, j);
if (mx < f[i][j])
mx = f[i][j];
}
printf("%s: %d\n", s, mx + 1);
}
return 0;
}
代码(dp):
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int mx[] = { 1, 0, -1, 0 };
int my[] = { 0, 1, 0, -1 };
int r, c;
struct node
{
int x, y, h;
} a[10005];
int m[103][103], f[103][103];
bool cmp(node a, node b)
{
return a.h<b.h;
}
bool check(int x, int y)
{
return (x >= 0 && y >= 0 && x<r && y<c);
}
int main()
{
int n;
scanf("%d", &n);
while (n--)
{
memset(f, 0, sizeof(f));
char name[103];
scanf("%s%d%d", name, &r, &c);
int i, j, p = 0;
for (i = 0; i<r; i++)
for (j = 0; j<c; j++)
{
scanf("%d", &m[i][j]);
a[p].x = i;
a[p].y = j;
a[p].h = m[i][j];
p++;
}
sort(a, a + p, cmp);
for (i = 0; i<p; i++)
{
int x, y, h;
x = a[i].x;
y = a[i].y;
h = a[i].h;
for (j = 0; j<4; j++)
{
int tx = x + mx[j], ty = y + my[j];
if (check(tx, ty) && m[tx][ty]>h)
f[tx][ty] = max(f[tx][ty], f[x][y] + 1);
}
}
int ans = 0;
for (i = 0; i<p; i++)
ans = max(ans, f[a[i].x][a[i].y]);
printf("%s: %d\n", name, ans + 1);
}
return 0;
}