第九届蓝桥杯第八题天气变暖


一.题意理解

此处有两点需要明确

1.海岛减少数

题目所描述的是,#块相连即是一个海岛,如果海岛的所有块都消失则该海岛消失。(一定要反复读题,因为我就理解错了, 想着还有一个海岛分裂为两个海岛的情况)

明确了这个之后,我们的问题就会转化为,确定该海岛是否存在不会沉的块。若存在,则该海岛不会沉。

(问题解决可用dfs搜索的时候,标记每个海岛是否存在这样的点,最后用总数减去沉岛屿的个数就是减少数。或者每次dfs,用flag标记,如果不存在这样的点就减少数++)

2.边界问题

我之所以说这个问题也是因为我没好好读题,因为题目中明确地图边界都是海。但没看见的应该不止我一个。但既然想到了就解决一下。

/*example
###
.#.
… 我们就定义这种情况该岛屿是有一个不会沉的点的
*/

// check 数组返回true代表该点不会沉
bool check(int x, int y) {
	if (x-1>=0 && maps[x-1][y] == '.') return false;
	if (x+1>=0 && maps[x+1][y] == '.') return false;
	if (y-1>=0 && maps[x][y-1] == '.') return false;
	if (y+1>=0 && maps[x][y+1] == '.') return false;
	return true;
}

以上check数组即可解决该问题

二.题目参考代码

#include <iostream>
using namespace std;
int n;
char maps[1005][1005];
int vis[1005][1005];
// 表示每个海岛拥有不会被淹没格子的个数 
int gridPerLand[1000];
int change[4][2] = {{1,0}, {-1,0}, {0,1}, {0,-1}};

/*bool check(int x, int y) {
	if (x-1>=0 && maps[x-1][y] == '.') return false;
	if (x+1>=0 && maps[x+1][y] == '.') return false;
	if (y-1>=0 && maps[x][y-1] == '.') return false;
	if (y+1>=0 && maps[x][y+1] == '.') return false;
	return true;
}*/

void dfs(int x, int y, int index) {
	if (x >= n || y >= n || x < 0 || y < 0 || vis[x][y] || maps[x][y] == '.') return;
	vis[x][y] = 1;
	//if(check(x, y)) gridPerLand[index]++; 
	// 题目声明最外边都是海洋,所以无需考虑边界问题直接四面判断是否都是陆地
	if (maps[x-1][y] == '#' && maps[x+1][y] == '#' && maps[x][y+1] == '#' && maps[x][y-1] == '#') gridPerLand[index]++;
	/*example
		###
		.#.
		... 这种情况该岛屿是有一个不会沉的点的 
	*/ 
	for (int i=0; i<4; i++) {
		dfs(x + change[i][0], y + change[i][1], index);
	}
}


int main() {
	scanf("%d", &n);
	for (int i=0; i<n; i++) {
		for (int j=0; j<n; j++) {
			cin >> maps[i][j];
		}
	}
	int island = 0;
	for(int i=0; i<n; i++) {
		for (int j=0; j<n; j++) {
			if (vis[i][j] == 0 && maps[i][j] == '#') {
				island++;
				dfs(i, j, island);
			}
		}
	}
	int ans = 0;
	// 如果该海岛没有不会沉的点(即该海岛会沉)则ans++
	for (int i=1; i<=island; i++) {
		if (gridPerLand[i] == 0) ans++; 
	}
	cout << ans << endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值