引爆炸弹(dfs解法)

问题描述

在一个n×m 的方格地图上,某些方格上放置着炸弹。手动引爆一个炸弹以后,炸弹会把炸弹所在的行和列上的所有炸弹引爆,被引爆的炸弹又能引爆其他炸弹,这样连锁下去。

现在为了引爆地图上的所有炸弹,需要手动引爆其中一些炸弹,为了把危险程度降到最低,请算出最少手动引爆多少个炸弹可以把地图上的所有炸弹引爆。

输入格式

第一行输两个整数 n,m;n,m,用空格隔开。
接下来 n行,每行输入一个长度为 m 的字符串,表示地图信息。
0表示没有炸弹,1表示炸弹。
数据约定:
对于 60% 的数据:1 <= n,m <= 100;
对于 100%的数据:1 <= n,m <= 1000;
数据量比较大,不建议用cin输入。

输出格式

输出一个整数,表示最少需要手动引爆的炸弹数。

样例输入
5 5
00010
00010
01001
10001
01000
样例输出
2

示例代码:

/**
	该题说要算出手动引爆炸弹的最小个数
	其实只要中规中矩从mp[0][0]按正常顺序遍历第一个炸弹开始引爆就可以了(想多的话还会特地找这个最小值,其实大可不必) 
	原因:
		一个炸弹引爆会牵扯到一行炸弹和一列炸弹,被牵扯到的炸弹也会这样牵扯下去,产生连锁效应 
*/ 

#include<cstdio>
char mp[1005][1005];	//存储地图信息
int n, m;    //存储行列的值 
int cnt;     //用来记录手动引爆的次数 
bool vx[1005], vy[1005];	//标记行列有没有被引爆(用来避免重复引爆) 

void dfs(int x, int y ) {
	//printf("(%d,%d)\n",x,y);
	
	mp[x][y] = '0';	//被引爆的炸弹就置为0 避免重复引爆 
	
	if(!vx[x]) {	// x 行没有被引爆则进行引爆 
	
		vx[x] = true;	//x 行标记为 已引爆状态	 
		
		for(int i = 0; i < m; i ++) {	//在 x 行上寻找其他的炸弹 
			if(mp[x][i] == '1') {	//找到炸弹则继续引爆该炸弹 
				dfs(x, i);	
			}
		}
	}
	if(!vy[y]) {	// y 列没有被引爆则进行引爆 
		
		vy[y] = true;   //y 行列标记为 已引爆状态	
		
		for(int i = 0; i < n; i ++) {    //在 y 列上寻找其他的炸弹 
			if(mp[i][y] == '1') {    //找到炸弹则继续引爆该炸弹 
				dfs(i, y);
			}
		}
	}
} 

int main() {
	scanf("%d%d",&n,&m);
	
	for (int i = 0; i < n; i ++) {
		scanf("%s",&mp[i]);
	}
	
	for (int i = 0; i < n; i ++) {
		for (int j = 0; j < m; j ++) {
			
			if (mp[i][j] == '1') {	//找到一个炸弹就开始手动引爆 
				cnt ++;	//手动引爆次数 +1 
				dfs(i, j);	//深搜传入炸弹的坐标 
			}
		}
	}
	printf("%d\n", cnt);
	return 0;
} 
posted @ 2020-02-13 23:27  橡北  阅读(738)  评论(0)    收藏  举报