P3456 [POI2007]GRZ-Ridges and Valleys

知识点:深度优先搜索

难度: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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值