UVa10285 - Longest Run on a Snowboard

思路

假设从( x, y )出发,并且从( x, y )出发所能走的最长路为 d[x][y],那么设想如果( x - 1, y )的值(即题目所给的高度)要小于(x,y),那么d[x-1][y] + 1 有可能就是我们所要求的d[x][y],因为这条路是单向的,只可能从较小的(x-1, y)走向(x,y)。如果考虑四个方向,用(x’, y’)表示(x , y)上下左右四个方向,那么d[x][y] = max(d[x’][y’]) + 1,且 (x’, y’)上的值要小于(x, y)。那么从这个方程可以看出这实际上可以采用 DFS 加上 dp 的做法,或者称之为记忆化搜索。而 搜索 的终点则是某点(x, y)的四周都比他大,则返回 1。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/*
* AC @ Nov 26th 2015
* Run Time : 0.003s
*/
#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int, int> pr_int;

int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
const int MAXN = 100 + 40;
int height[MAXN][MAXN], d[MAXN][MAXN];
string name;
int rows, cols;

void read() {
cin >> name >> rows >> cols;
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
cin >> height[i][j];
}
}
}

int dp(int x, int y) {
if (d[x][y] != -1) {
return d[x][y];
}
int ans = 1;
for (int i = 0; i < 4; ++ i) {
int nx = x + dir[i][0], ny = y + dir[i][1];
//cout << nx << " : " << ny << " " << height[x][y] << " " << height[nx][ny] << endl;
if (nx >=0 && nx < rows && ny >=0 && ny < cols && height[x][y] > height[nx][ny]) {
ans = max(dp(nx, ny) + 1, ans);
}
}
//cout << x << " " << y << endl;
return d[x][y] = ans;
}

int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while(T --) {
read();
int ans = 1;
memset(d, -1, sizeof(d));
for (int i = 0; i < rows; ++ i) {
for (int j = 0; j < cols; ++ j) {
ans = max(ans, dp(i, j));
}
}
cout << name << ": " << ans << endl;
}
return 0;
}