题目:
算法竞赛入门经典第二版 刘汝佳 P162例题6-12
思路:
恕臣愚钝 这题目我一开始都没看懂两个八连块怎么数出来的。。
仔细读了N遍。。原来就是数油田,相连的就属于同一块,所以这里是两坨油田。。
之前老师上课都讲过原题哎可惜我没听
八连块的八指的是以一个符号为中心,九宫格中其他的八个,也就是递归遍历的范围
看完书自己再梳理一下思路:
- 递归: 从第一个开始遍历符号,如果是油田 ‘ @’,则将其编号并且查询附近的8个格子,一旦查找到有油田的,编上相同的序号并以该油田为中心查找附近的8个格子。(实现了DFS)
- 标记和计数:用一个数组,初始化都存的0,第一次遇到油田即从1开始存储(cnt),只要是相邻的8个格子中的油田编号都相同,没有相同的就cnt加一,说明一个油田已经查找完毕,如果再发现油田就是第二个了。最后直接输出 cnt 就是有 “几坨” 油田
具体的代码实现:
- 两个数组,一个字符型,一个 int 型用于存储编号cnt
- 编号函数(递归函数),一旦查找到油田就将其编号,如果九宫格的其他8个格子里还有油田就递归调用继续编号。
- 编号可以用于判断状态,如出界、不是油田、没有遍历过,idx 数组的值都会是0.如果遍历过且是油田数组存的值就是非0
- 字符串输入,可以看到油田中没有空格输入,都是直接输入一行的字符串存储。(学到了。。因为我之前不会)
for(int i=0; i<m; i++)
scanf("%s",pic[i]);//字符串输入二维数组的一行字符
代码:
#include<cstdio>
#include<cstring>
const int maxn=100+5;
char pic[maxn][maxn];
int m,n,idx[maxn][maxn];
void dfs(int r,int c,int id)//编号函数
{
//对相邻的格子进行判断
if(r>=m||r<0||c>=n||c<0)return;//出界
if(pic[r][c]!='@'||idx[r][c]>0)return;//不是油田或者已经编号过的油田
//编号油田并且以该油田为中心找相邻的八个格子
idx[r][c]=id;
for(int dr=-1;dr<=1;dr++)
for(int dc=-1;dc<=1;dc++)
if(dr!=0 || dc!=0) dfs(r+dr,c+dc,id);//递归实现DFS
}
int main()
{
while(scanf("%d%d", &m, &n)==2 && m && n)
{
for(int i=0;i<m;i++)
scanf("%s",pic[i]);//通过字符串输入
memset(idx, 0, sizeof(idx));//初始化
int cnt=0;
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
if(pic[i][j]=='@' && idx[i][j]==0) dfs(i,j,++cnt);//如果是油田且没有编号就将其编号
printf("%d\n",cnt);
}
return 0;
}