问题描述:有一个大小为N*M的院子,雨后积水,八连通的积水被认为是链接在一起的。请求出园子里总共有多少水洼。
输入:N=10,M=12
园子如下:
W。。。。。。。。WW。
。WWW。。。。。WWW
。。。。WW。。。WW。
。。。。。。。。。WW。
。。。。。。。。。W。。
。。W。。。。。。W。。
。W。W。。。。。WW。
W。W。W。。。。。W。
。W。W。。。。。。W。
。。W。。。。。。。W。
(W表示积水,。表示没有积水,其中八联通的积水都是认为是一个)
输出:3
原理:使用宽度优先搜索,只要周围还有积水,就继续扩展宽度,直到周围八连通区域没有积水了,就返回,此时前面所有的积水被认为是一个。
源代码:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <stdlib.h>
using namespace std;
int n, m;
void wfs(vector<string> &water,int x,int y)
{
water[x][y] = '.';
//进行八连通检查
if ((x-1)>=0 && (y-1)>=0 && x-water[x - 1][y - 1] == 'W')wfs(water, x - 1, y - 1);
if ((x-1)>=0 && water[x - 1][y] == 'W')wfs(water, x - 1, y);
if ((x-1)>=0 && (y+1)<m && water[x - 1][y + 1] == 'W')wfs(water, x - 1, y + 1);
if ((y-1)>=0 && water[x][y - 1] == 'W')wfs(water, x, y - 1);
if ((y+1)<m && water[x][y + 1] == 'W')wfs(water, x, y + 1);
if ((x+1)<n && (y-1)>=0 && water[x + 1][y - 1] == 'W')wfs(water, x + 1, y - 1);
if ((x+1) < n && water[x + 1][y] == 'W')wfs(water, x + 1, y);
if ((x+1) < n && (y+1)<m && water[x + 1][y + 1] == 'W')wfs(water, x + 1, y + 1);
}
int main(void)
{
fstream f;
f.open("D:\\water.txt", ios::in);//只读打开
char tmp[1024];
vector<string> water;
int count = 0;
while (!f.eof())
{
f >> tmp;
water.push_back(tmp);
}
cout << "please input n and m:";
cin >> n >> m;
#include <fstream>
#include <string>
#include <vector>
#include <stdlib.h>
using namespace std;
int n, m;
void wfs(vector<string> &water,int x,int y)
{
water[x][y] = '.';
//进行八连通检查
if ((x-1)>=0 && (y-1)>=0 && x-water[x - 1][y - 1] == 'W')wfs(water, x - 1, y - 1);
if ((x-1)>=0 && water[x - 1][y] == 'W')wfs(water, x - 1, y);
if ((x-1)>=0 && (y+1)<m && water[x - 1][y + 1] == 'W')wfs(water, x - 1, y + 1);
if ((y-1)>=0 && water[x][y - 1] == 'W')wfs(water, x, y - 1);
if ((y+1)<m && water[x][y + 1] == 'W')wfs(water, x, y + 1);
if ((x+1)<n && (y-1)>=0 && water[x + 1][y - 1] == 'W')wfs(water, x + 1, y - 1);
if ((x+1) < n && water[x + 1][y] == 'W')wfs(water, x + 1, y);
if ((x+1) < n && (y+1)<m && water[x + 1][y + 1] == 'W')wfs(water, x + 1, y + 1);
}
int main(void)
{
fstream f;
f.open("D:\\water.txt", ios::in);//只读打开
char tmp[1024];
vector<string> water;
int count = 0;
while (!f.eof())
{
f >> tmp;
water.push_back(tmp);
}
cout << "please input n and m:";
cin >> n >> m;
//下面进行宽度优先搜索
for (int i = 0; i < water.size(); i++)
for (int j = 0; j < water[i].size(); j++)
{
if (water[i][j] == 'W')
{
wfs(water, i, j);
count++;
}
}
for (int i = 0; i < water.size(); i++)
for (int j = 0; j < water[i].size(); j++)
{
if (water[i][j] == 'W')
{
wfs(water, i, j);
count++;
}
}
cout << "sum water is "<<count<<endl;
f.close();
return 0;
}
f.close();
return 0;
}
把周围的所有相邻积水都换成‘。’,所以宽度优先的次数就是水洼的个数。想法很巧妙~编程的时候千万不要用一贯的思想,那样会很累,多练练这些算法,找到捷径,养成一个好的思考方式~