题意:从一个数开始,可以往上下左右四个方向走,要求走到的的数比当前的数小,这条路最多能经过多少个数。
设f[i][j]表示以编号a[i][j]这个格子为起点,所能走的步数,那么显然有f[i][j] = f[i - 1][j] 、f[i + 1][j] 、f[i][j - 1] 、f[i][j + 1]这四个数里面较大的一个再加上1(当然还要考虑能否到达的情况)。
那么问题来了:挖掘机技术哪家强应该怎么来确定枚举顺序呢?
在之前的一些题目里,题目是有明显的递推先后顺序的,然而这一题似乎不太明显。当前格子的步数取决于旁边格子的步数,旁边格子的步数又取决于旁边的旁边的格子的步数,而且它们还会互相影响。那该怎么办呢?看看递推式,想要确定f[i][j],必须先确定它旁边能到达的格子的f值,这其实就是一个递归的过程。用一个函数work(i, j)来求[i, j]格子的值, 那么work(i, j)首先检查f[i][j]是否已经求出来了,如果没有,它就去递归地求[i, j]格子旁边能到达的格子的值(这个递归一定会停下来的,因为总能找到一个格子,它周围的数都比它大。注意处理边界情况!),然后更新并返回f[i][j]的值,否则直接返回f[i][j]。这样对所有格子处理一遍就好了。当然,如果当前处理到的格子已经求出了f[i][j],就没必要再调用work了。
设f[i][j]表示以编号a[i][j]这个格子为起点,所能走的步数,那么显然有f[i][j] = f[i - 1][j] 、f[i + 1][j] 、f[i][j - 1] 、f[i][j + 1]这四个数里面较大的一个再加上1(当然还要考虑能否到达的情况)。
那么问题来了:
在之前的一些题目里,题目是有明显的递推先后顺序的,然而这一题似乎不太明显。当前格子的步数取决于旁边格子的步数,旁边格子的步数又取决于旁边的旁边的格子的步数,而且它们还会互相影响。那该怎么办呢?看看递推式,想要确定f[i][j],必须先确定它旁边能到达的格子的f值,这其实就是一个递归的过程。用一个函数work(i, j)来求[i, j]格子的值, 那么work(i, j)首先检查f[i][j]是否已经求出来了,如果没有,它就去递归地求[i, j]格子旁边能到达的格子的值(这个递归一定会停下来的,因为总能找到一个格子,它周围的数都比它大。注意处理边界情况!),然后更新并返回f[i][j]的值,否则直接返回f[i][j]。这样对所有格子处理一遍就好了。当然,如果当前处理到的格子已经求出了f[i][j],就没必要再调用work了。
#include <iostream>
#include <cmath>
#include <cstdio>
#include <vector>
#include <set>
#include <cstring>
#include <climits>
#include <map>
#include <string>
#include <algorithm>
#include <queue>
using namespace std;
int c, r, height[102][102], f[102][102];
bool vis[102][102];
const int movex[] = { -1, 0, 1, 0};
const int movey[] = {0, 1, 0, -1};
int work(int x, int y);
int main() {
cin >> r >> c;
for (int i = 1; i <= r; ++i) {
for (int j = 1; j <= c; ++j) {
cin >> height[i][j];
}
}
int ans = 0;
for (int i = 1; i <= r; ++i) {
for (int j = 1; j <= c; ++j) {
if (!f[i][j])
f[i][j] = work(i, j);
ans = max(ans, f[i][j]);
}
}
cout << ans + 1<< endl;
return 0;
}
int work(int x, int y) {
if (!f[x][y]) {
int newx, newy;
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
newx = x + movex[i];
newy = y + movey[i];
if (newx >= 1 && newx <= r && newy >= 1 && newy <= c
&& height[x][y] > height[newx][newy])
f[x][y] = max(f[x][y], work(newx, newy) + 1);
}
}
}
return f[x][y];
}
最后输出+1,是因为我的f[i][j]代表的是走了多少步,还要加上起点才是正确答案。