解题思路:
将问题看做从一个岛屿(x, y)点向外扩散红色水
大陆上是4通路扩散,到海里就是8通路扩散
为啥大陆上要4通路?因为如下两座岛,是不相连的,但是在大陆上8通路就会认为相连:
100 010 000
如果当前红色水扩散到地图边界了(要出地图了),就表示当前(x, y)出来的岛屿不是子岛屿,答案就加一
扩散的时候,标记岛屿不再访问了,但是海水访问过的要复原,以便下次访问
详细看代码注释
参考代码:
#include using namespace std; int m, n; vector d; bool v[51][51]; bool flag; int d1[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; int d2[8][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}, {1, 1}, {1, -1}, {-1, -1}, {-1, 1}}; /** * 将问题看做从一个岛屿(x, y)点向外扩散红色水 * 大陆上是4通路扩散,到海里就是8通路扩散 * 为啥大陆上要4通路,因为如下两座岛,是不相连的,但是在大陆上8通路就会认为相连: * 100 * 010 * 000 * 如果当前红色水扩散到地图边界了(要出地图了),就表示当前(x, y)出来的岛屿不是子岛屿,答案就加一 * 扩散的时候,标记岛屿不再访问了,但是海水访问过的要复原,以便下次访问 */ void flooding(int x, int y, int bak) { // printf("%d %d %d\n", x, y, bak); // 如果扩散到边界了,说明当前岛屿没有被其他岛屿包住,不是子岛屿 if (x < 0 || x >= m || y < 0 || y >= n) {flag = true; return;} int nb = d[x][y] == '0' ? 0 : 1; // 当前地块的种类,存整数 if (bak == 0 && nb == 1) return; // 如果从0到1,就表示从海水碰到其他岛屿边界了,停止扩散了 if (v[x][y]) return; // 如果已经访问过了,那么就不继续扩散了 v[x][y] = true; if (nb == 1) { // 如果当前是岛屿,这时已经默认从1扩散到1的,就继续向4通路扩散 for (auto [a, b] : d1) flooding(x + a, y + b, nb); } if (nb == 0) { // 如果当前是海水,这时不论是从0/1扩散到0的,就继续向8通路扩散 for (auto [a, b] : d2) flooding(x + a, y + b, nb); } } // 复原海水的访问状态 void flush_zero() { for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (v[i][j] && d[i][j] == '0') v[i][j] = false; } } } int main() { int T; cin >> T; while (T--) { cin >> m >> n; d.clear(); memset(v, false, sizeof(v)); for (int i = 0; i < m; i++) { string s; cin >> s; d.push_back(s); } int ans = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (d[i][j] == '0' || v[i][j]) continue; flag = false; flooding(i, j, 1); if (flag) ans++; flush_zero(); } } cout << ans << endl; } return 0; }
0.0分
3 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复