知识点:深度优先搜索
难度:4
这个题如果做过了紫书第6章深搜的例题,就是那个拓扑字符的古文字问题,应该是很简单的,我12分钟就过了这个题,感觉还是要过段时间再写比较好,毕竟现在对那道蓝题有很深的印象,还有为什么说这个题是深搜,因为连通块的划分一般用深搜,虽然广搜也可以
思路很简单,就是先一个遍历,用深搜划分连通块,记录一下,就是进阶指南上面的那样,然后用第二深搜,遍历每个连通块,如果和当前连通块相邻的其它连通块的高度比当前的高,那么当前连通块就不是山峰,山谷的判断同理,所以,,很简单的,12分钟过了
这种遍历当前连通块,并且跟与它相邻的连通块比较,应该也是这类题目的一个基础小技巧,
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
int n, cnt, a[N][N], b[N][N], c[N][N], ok1, ok2;
int dx[8] = {-1, -1, -1, 0, 1, 1, 1, 0};
int dy[8] = {-1, 0, 1, 1, 1, 0, -1, -1};
void dfs(int x, int y) {
b[x][y] = cnt;
for (int i = 0; i < 8; i++) {
int x1 = x + dx[i];
int y1 = y + dy[i];
if (x1 < 0 || x1 >= n || y1 < 0 || y1 >= n) continue;
if (b[x1][y1] || a[x1][y1] != a[x][y]) continue;
dfs(x1, y1);
}
}
void dfs2(int x, int y) {
c[x][y] = 1;
for (int i = 0; i < 8; i++) {
int x1 = x + dx[i];
int y1 = y + dy[i];
if (x1 < 0 || x1 >= n || y1 < 0 || y1 >= n) continue;
if (b[x1][y1] != b[x][y]) {
if (a[x1][y1] > a[x][y]) ok1 = 0;
if (a[x1][y1] < a[x][y]) ok2 = 0;
continue;
}
if (c[x1][y1]) continue;
dfs2(x1, y1);
}
}
int main() {
cin >> n;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) cin >> a[i][j];
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (!b[i][j]) { cnt++; dfs(i, j); }
}
}
int ans1 = 0, ans2 = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (!c[i][j]) {
ok1 = 1; ok2 = 1;
dfs2(i, j);
if (ok1) ans1++;
if (ok2) ans2++;
}
}
}
cout << ans1 << " " << ans2;
return 0;
}