uva572题解-oil deposits(bfs图)
题干
输入多个 m 行 n 列的矩阵,用 0 0 表示输入结束。找出有多少块石油区域,用 @ 代表石油,假如两个 @ 在横,竖或对角线上相邻,就说它们位于同一区域,对于每个输入,输出一个数表示有几个石油区域。
其中1≤m≤100and1≤n≤100.
样例输入:
1 1
*
3 5
@@*
@
@@*
1 8
@@***@
5 5
****@
@@@
@**@
@@@@
@@**@
0 0
样例输出:
0
1
2
2
思路
典型的求连通图个数问题,用bfs搜图即可。
基本逻辑是:若是一个点是@且没被遍历过,就是新的油田,然后找到这块完整油田并打上标记,表示我们已经找过计数了
找完整油田的过程就是bfs,传入这个油田点,给相邻八个方向的没找过的油田打上标记,没找到或者到边界就return。
细节
1.bfs八个方向的写法
我们定义一个方向数组,让x+dx[i],y+dy[i]代表八个方向的某一个
以(x,y)为中心从左到右看dx,向左有左上,正左,左下三个,即三个-1.
故dx={-1,-1,-1,0,0,1,1,1}
而dy对应-1 -1 -1分别是-1,0,1(代表左上,正左,左下)
故dy={-1,0,1,-1,1,-1,0,1}
这样我们一个for循环就可以递归出8次bfs了(要写8个bfs语句也可,看起来臃肿了点)
2.vector?
紫书上面没用vector,而是定义了一个足够大的二维数组(紫书题干没写nm范围...),去代替vector,代码看起来相当简洁
代码
#include<iostream>
#include<vector>
using namespace std;
void bfs(vector<vector<char>> &oil,vector<vector<bool>> & track,int n,int m,int x,int y);
int main(){
int n,m;
while(true){
cin>>n>>m;
cin.ignore();
if(!n||!m)break;
vector<vector<char>> oil(n,vector<char>(m));
vector<vector<bool>> track(n,vector<bool>(m,false));
int count=0;
for(int i=0;i<n;i++){
string arr;
getline(cin,arr);
for(int j=0;j<m;j++)oil[i][j]=arr[j];
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(oil[i][j]=='@'&&!track[i][j]){
count++;
bfs(oil,track,n,m,i,j);
}
}
}
cout<<count<<endl;
}
}
void bfs(vector<vector<char>> &oil,vector<vector<bool>> &track,int n,int m,int x,int y){
if(x<0||x>=n||y<0||y>=m)return ;
if(oil[x][y]=='*'||track[x][y]==true) return ;
track[x][y]=true;
int dx[8]={-1,-1,-1,0,0,1,1,1};
int dy[8]={-1,0,1,-1,1,-1,0,1};
for(int i=0;i<8;i++){
bfs(oil,track,n,m,x+dx[i],y+dy[i]);
}
}

浙公网安备 33010602011771号