描述
有一块N×M的土地,雨后积起了水,有水标记为‘W’,干燥为‘.’。八连通的积水被认为是连接在一起的。请求出院子里共有多少水洼?
格式
输入格式
第一行为N,M(1≤N,M≤110)。 下面为N*M的土地示意图。
输出格式
一行,共有的水洼数。
样例
输入样例
10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.
输出样例
3
限制
时间限制: 1000 ms
内存限制: 65536 KB
一开始看题目时,怎么都看不懂这题意,感觉这字里行间是不是少了点什么描述?比如说“八连通的积水被认为是连接在一起的”这一句是不是结尾处还有话没说完。于是我就搜了下该题目,没有少字,就是这样的表述。题目的意思是找极大连通图,你把题目给的样例看成一张图,图中是不是三处有积水互相不连通,而这三处积水块内是连通的,如果‘W’的上、下、左、右、左上、右上、左下、右下都是‘.’的话,该处就是一处水洼,但这三处积水是有很多‘W’组成的,每个‘W’的上、下、左、右、左上、右上、左下、右下八个位置都不全是‘.’,这怎么找水洼?我的理解是:因为这些‘W’是联通的,所以可以将它们看作一个整体,对于这个整体,如果小规模的积水‘W’是水洼,那么这个整体也可以看做一个水洼。所以进行查找时,遇到第一个‘W’时,开始对它的八个方向进行查找,遇到下一个‘W’后,标记为‘.’,然后从这个被标记的‘W’开始进行下一次查找,循环直到该积水处的最后一个‘W’的八个方向都是‘.’为止,也就找到一处水洼。当搜索完整个土地,那么会找到所有的水洼。
题目有深搜和广搜两种搜索思路,深搜是一条路直走到低然后走下一条路,广搜是用队列,可以认为是同时走多条路,不过是有先后顺序走。
题目偏向于模板型,读懂题目意思后你会发现不难名单不要犯一些小错误。。。比如当使用scanf()输入时,忘记用getchar()吸收回车符。。。用cin可以不管。
//dfs
#include
using namespace std;
char a[115][115];
char que[115];
int dx[8] = {-1, 0, 1, -1, 1, -1, 0, 1};
int dy[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
int ans=0, n, m;;
void dfs(int, int);
void linkLake();
int main()
{
scanf ("%d %d", &n, &m);
//getchar(); “血”的教训,一定不要忘了吸回车,当只过了60%时,
//我查了好久才发现是这里除了问题。。。
for (int i=0; i> a[i][j]);
}
//getchar();
}
linkLake();
printf ("%d\n", ans);
return 0;
}
void linkLake() {
for (int i=0; i= 0 && tmpy < m && tmpy >=0 && a[tmpx][tmpy] == 'W') {
a[tmpx][tmpy] = '.';
dfs(tmpx, tmpy);
}
}
}
bfs广搜,因为我看很多解法是用stl的queue来做的,所以我想用用数组充当队列试试,如果用stl的queue,则一般的写法是命名结构体,queue的数据类型是该结构体。
//bfs
#include
using namespace std;
char a[115][115];
int que[10005][3];
int dx[8] = {-1, 0, 1, -1, 1, -1, 0, 1};
int dy[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
int ans=0, n, m;;
void bfs(int, int);
int main()
{
scanf ("%d %d", &n, &m);
for (int i=0; i> a[i][j];
}
}
for (int i=0; i= 0 && tmpy < m && tmpy >=0 && a[tmpx][tmpy] == 'W') {
a[tmpx][tmpy] = '.';
tail++;
que[tail][1] = tmpx;
que[tail][2] = tmpy;
}
}
head++;
}
}