![](http://hi.csdn.net/attachment/201107/5/0_1309879730H6bi.gif)
已知农场可以用MXN的矩阵表示(1 <= N <= 100; 1 <= M <= 100),矩阵中的每个元素代表农场的每一小块土地,元素要么为‘W’(表示被水淹没),要么为'.'(表示没有被水淹没)。
现在,我们可怜的花心龟看着自己苦心经营的农场变成这样,心都碎了,他只有一个想法,统计出自己的农场到底被多少片水域所淹没。
一片水域是由连续的若干相邻的小块地组成的,并且小每块地周围的八小块地都可以看做是和它相邻的。要求给出花心龟农场的的现状,并计算有多少块水域。(感谢热情的网友提供的题目)
例如:
输入农场规格(N和M):
10 12
输入农场现状(用矩阵表示):
![](http://hi.csdn.net/attachment/201107/5/0_1309879726cGI8.gif)
输出水域块数:
3
花心龟请来了一位帅气的程序员,这位程序员看了农场的状况之后,他认为要解决这个问题,首先要分以下几个步骤进行思考(算法思路):
步骤 一、用如下数据结构,以一维数组的形式保存农场状况
struct FarmData{
char ch;
int fDetected;//是否已探测到水的标志
};
FarmData *p=(FarmData *)calloc(N*M,sizeof(FarmData));
步骤 二、对整个一维数组进行遍历,每当遍历到一个元素数据为‘w’时且该元素的fDetected标志为0(说明未对该区域进行查明),做第三个步骤,直到遍历完每个元素为止。
步骤 三、当步骤二遍历到未查明的水时,将该元素入栈保存。接着每次取栈中元素,并将其fDetected标志为1, 然后对其周围八个位置进行查明,如果是水则入栈保存,如此直到栈中没有任何数据为止。
步骤四、计数,每次步骤二遍历到一个未查明的W时计数器就加1,回到步骤二(因为每次查明到未查明的元素W时,都会将其周围的W标记为已查明,所以计数器最终的结果就代表整个农场有多少块水域)
这位程序员经过几番思考之后,终于在电脑下打下了这一段程序(算法实现代码):
/*
* copy right by Zhanhang
* qq:273711460
* e-Mail:huaxin.turtle@gmail.com
* HomePage:http://blog.csdn.net/zhanxinhang
*/
#include <stdio.h>
#include <malloc.h>
struct FarmData{
char ch;
int fDetected;//是否已探测到水的标志
};
int main()
{
int N=0,M=0,i=0,j=0,k=0,counter=0,T=0,c=0,r=0,currentP=0;
int stack[50]={0}; //栈
FarmData *p;
//输入农场规格
while(1)
{
printf("please input N,M:");
scanf("%d,%d",&N,&M);
if(1<=N && 100>=N &&
1<=M && 100>=M)
break;
else
printf("input error!try again\n");
}
//初始化动态数组
p=(FarmData *)calloc(N*M,sizeof(FarmData));
//输入农场的现状
printf("please show the state of farm:\n");
while((p[i].ch=getchar())&&i<N*M)
if(p[i].ch!='\n')
i++;
#define POP() stack[--T]
#define PUSH(x) stack[T++]=x
#define P(row,col) (currentP=M*(row)+col,p[currentP]) //用二维数组的形式表示一维数组
//计算水域
for(i=0;i<N*M;i++)
{
if(p[i].fDetected||p[i].ch=='.')
continue;
PUSH(i); //入栈
while(T)
{
if(!p[(k=POP())].fDetected && p[k].ch=='w')
{
r=k/M; //行
c=k%M; //列
p[k].fDetected=1;
//判断周围八个点是否有水,有则入栈保存
if(P(r-1,c).ch == 'w'&&!p[currentP].fDetected && r-1>=0)
PUSH(currentP);
if(P(r-1,c+1).ch == 'w'&&!p[currentP].fDetected && c+1<M && r-1>=0)
PUSH(currentP);
if(P(r-1,c-1).ch == 'w'&&!p[currentP].fDetected && c-1>=0 && r-1>=0)
PUSH(currentP);
if(P(r,c+1).ch == 'w'&&!p[currentP].fDetected && c+1<M)
PUSH(currentP);
if(P(r+1,c+1).ch == 'w'&&!p[currentP].fDetected && r+1<N && c+1<M)
PUSH(currentP);
if(P(r+1,c).ch == 'w'&&!p[currentP].fDetected && r+1<N)
PUSH(currentP);
if(P(r-1,c-1).ch == 'w'&&!p[currentP].fDetected && c-1>=0 && r-1>=0)
PUSH(currentP);
if(P(r,c-1).ch == 'w'&&!p[currentP].fDetected && c-1>=0)
PUSH(currentP);
}
}
T=0; //清栈
counter++;//计数
}
#undef P
#undef POP
#undef PUSH
printf("the number of regions covered by water is:%d\n",counter);
free(p);
return 0;
}
小结:分而治之。首先在遍历整个数组中,分为两个决策阶段,一就是遍历到未查明的水,便对其周围的水进行标记以及计数一块水域,二就是遍历到已标记查明的水或不是水,则进行下一次循环,最终遍历的结束就是问题的解决。
欢迎学习交流 转载不忘注明出处! ^_^
======= welcome to my HomePage(http://blog.csdn.net/zhanxinhang) to have a communication =======