引爆炸弹(dfs解法)
Posted zhixiangshu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了引爆炸弹(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)
",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
", cnt);
return 0;
}
以上是关于引爆炸弹(dfs解法)的主要内容,如果未能解决你的问题,请参考以下文章
P5025 [SNOI2017]炸弹 线段树优化建图+缩点+DAG图上DP