知识点:拓扑排序,动态规划,图论建模
刚才闲就把洛谷上面的滑雪题写了,谁知道打开书一看,这个居然是入门经典习题第一题,并且两个题基本一模一样,不知道是谁借鉴谁的,这个题我用的方法就是建图,拓扑排序,然后逆序动态规划,算是这类题的老套路,然后这个题边界条件是,没有后继结点的点的DP值是1,这个需要注意,然后这个DP是不指定起点和终点的,目前就会这一种递推的方法,这类题基本都是这样子写的
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 5;
const int M = 4e4 + 5;
int n, m, a[105][105], ind[N], b[N], cnt, f[N];
int tot, ver[M], head[N], nxt[M];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
void add(int x, int y) {
ver[++tot] = y;
nxt[tot] = head[x]; head[x] = tot;
}
void toposort() {
queue<int> q;
for (int i = 1; i <= n * m; i++) {
if (!ind[i]) q.push(i);
}
while (!q.empty()) {
int now = q.front(); q.pop();
b[++cnt] = now;
for (int i = head[now]; i; i = nxt[i]) {
if (--ind[ver[i]] == 0) q.push(ver[i]);
}
}
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
scanf("%d", &a[i][j]);
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
for (int k = 0; k < 4; k++) {
int x = i + dx[k], y = j + dy[k];
if (x < 1 || x > n || y < 1 || y > m) continue;
if (a[i][j] > a[x][y]) {
add((i - 1) * m + j, (x - 1) * m + y);
ind[(x - 1) * m + y]++;
}
}
}
}
toposort();
int ans = 0;
for (int i = n * m; i >= 1; i--) {
if (!head[b[i]]) {
f[b[i]] = 1;
} else {
for (int j = head[b[i]]; j; j = nxt[j]) {
f[b[i]] = max(f[b[i]], f[ver[j]] + 1);
}
}
ans = max(ans, f[b[i]]);
}
printf("%d", ans);
return 0;
}