心碎的花心龟农场遭遇洪水,雇一程序员帮忙编写程序计算损失(算法)

勤劳的花心龟日复一日的经营着自己的农场,投注了自己毕生的心血。但是让他心碎的是最近暴雨连连,农场也受到波及,很多区域都被淹没了。

       已知农场可以用MXN的矩阵表示(1 <= N <= 100; 1 <= M <= 100),矩阵中的每个元素代表农场的每一小块土地,元素要么为‘W’(表示被水淹没),要么为'.'(表示没有被水淹没)。
       现在,我们可怜的花心龟看着自己苦心经营的农场变成这样,心都碎了,他只有一个想法,统计出自己的农场到底被多少片水域所淹没。
       一片水域是由连续的若干相邻的小块地组成的,并且小每块地周围的八小块地都可以看做是和它相邻的。要求给出花心龟农场的的现状,并计算有多少块水域。(感谢热情的网友提供的题目)

例如:

输入农场规格(N和M):

10  12

输入农场现状(用矩阵表示):


输出水域块数:

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 =======


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 31
    评论
评论 31
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值