大意:
由于最近的降水,农夫约翰的农田里积了水,农田由一个N x M的矩形表示。有水标记为‘W’,干燥标记为‘.’。农夫约翰想弄清楚农田里有多少个水塘。八连通的积水被认为是连在一起的。现给出了农夫约翰的农田图,确定他有多少个池塘。
输入:第一行,两个由空格间隔开的整数:M和N;第2到n+1行,每行m个字符,代表农田的每一行。每个字符是‘W’或者‘.’,字符之间没有空格。
输出:一行,农夫约翰农田里的水塘的数量。
思路简析:
这道题乍看有点摸不着头脑,实际上还是蛮水的,比迷宫类型的还要简单一点,就是深搜。
输入后用for循环遍历整个农田,如果有水且没有被标记过,则水塘总数+1,标记当前坐标(也可以直接更改地图,就不用开标记数组),并从当前位置开始深搜。深搜部分:八连通(可能有点看不懂,其实就是指以它本身为中心的九宫格的其它八个方块)算一个湖,所以方向有8个,判断仍需要判断出界,如果有水且没有被标记过,便标记,水塘总数不用+1,这里是连起的,算一个水塘。由于是八连通的,所以由新联通的方块再联通上的也算是一个水塘(这里看样例也应该能理解吧),所以要以此为起点继续调用dfs搜索。这里湖的标记不用回溯。
奉上代码(自以为讲得很清楚了,就没有注释的必要了):
#include<cstdio> int r,c,sum,xx[8]={-1,-1,-1,0,0,1,1,1},yy[8]={-1,0,1,-1,1,-1,0,1}; char map[105][105]; bool mark[105][105]; bool check(int x,int y)//判断出界 { if(x>=0&&x<r&&y>=0&&y<c) return 1; return 0; } void dfs(int x,int y) { for(int i=0;i<8;i++) if(check(x+xx[i],y+yy[i])&&!mark[x+xx[i]][y+yy[i]]&&map[x][y]=='W')//如果有水且没有被标记过 { mark[x+xx[i]][y+yy[i]]=1;//标记该点已被搜索到,并以此为节点继续搜索 dfs(x+xx[i],y+yy[i]); } } int main() { scanf("%d %d",&r,&c); for(int i=0;i<r;i++) scanf("%s",map[i]); for(int i=0;i<r;i++) for(int j=0;j<c;j++) if(!mark[i][j]&&map[i][j]=='W')//如果有水且没有被标记过 { sum++;//数量+1,并以此为节点开始搜索 mark[i][j]=1; dfs(i,j); } printf("%d",sum); }
这里如果看懂了的话,AC了这道题建议再去看看1817和166的城堡问题,对做那道题有帮助哦!