計蒜客 A1139 引爆炸彈 DFS+剪枝
阿新 • • 發佈:2021-01-30
技術標籤:搜尋
題目描述
在一個 n × m n×m n×m 的方格地圖上,某些方格上放置著炸彈。手動引爆一個炸彈以後,
炸彈會把炸彈所在的行和列上的所有炸彈引爆,被引爆的炸彈又能引爆其他炸彈,這樣連鎖下去。
現在為了引爆地圖上的所有炸彈,需要手動引爆其中一些炸彈
為了把危險程度降到最低,請算出最少手動引爆多少個炸彈可以把地圖上的所有炸彈引爆。輸入格式
第一行輸兩個整數 n , m n,m n,m用空格隔開。
接下來 n n n 行,每行輸入一個長度為 m m m 的字串,表示地圖資訊。0
表示沒有炸彈,1
表示炸彈。
資料約定:
對於 60 % 60\%60% 的資料: 1 ≤ n , m ≤ 100 1≤n,m≤100 1≤n,m≤100;
對於 100 % 100\% 100% 的資料: 1 ≤ n , m ≤ 1000 1≤n,m≤1000 1≤n,m≤1000;
資料量比較大,不建議用cin
輸入。輸出格式
輸出一個整數,表示最少需要手動引爆的炸彈數。
輸入樣例
5 5 00010 00010 01001 10001 01000
輸出樣例
2
分析
炸彈會把炸彈所在的行和列上的所有炸彈引爆,被引爆的炸彈又能引爆其他炸彈,這樣連鎖下去
所以處於同一連通塊的炸彈的引爆順序不會對答案造成影響, 只要引爆一個炸彈, 和該炸彈處於同一連通塊的炸彈都會相繼被引爆
根據這一特點, 進行深搜
注意剪枝: 同一行(列)只引爆一次,否則會超時
實現
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1009;
int n, m;
int map[N][N];
bool row[N], col[N];
int sum;
void dfs(int x, int y) // 將與(x,y)處於同一連通塊的炸彈引爆
{
if(!col[y]) // 剪枝
{
col[y] = 1;
for(int i=0; i< n; i++)
{
if(map[i][y] == 1)
{
map[i][y] = 0;
dfs(i, y);
}
}
}
if(!row[x]) // 剪枝
{
row[x] = 1;
for(int i=0; i<m; i++)
{
if(map[x][i] == 1)
{
map[x][i] = 0;
dfs(x, i);
}
}
}
return;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
scanf("%1d",&map[i][j]);
for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
{
if(map[i][j] == 1)
{
sum++;
map[i][j] = 0;
dfs(i, j);
}
}
}
cout << sum << endl;
return 0;
}