浅析-啊哈算法-宝岛探险之小岛个数(深度优先)

浅析-啊哈算法-宝岛探险

欢迎大家批评指正

//啊哈算法114~116页代码
/*使用深度优先 求地图上的独立小岛数*/    
#include <stdio.h>
int a[51][51];
int book[51][51],n,m,sum;

void dfs(int x,int y,int color)
 {
   int k,tx,ty;
   //定义一个方向数组  依次向右、向下、向左、向上(即顺时针)
   int next[4][2]={{0,1},
                   {1,0},
                   {0,-1},
                   {-1,0}};
   a[x][y]=color;//对a[x][y]这个格子染色
  //四个方向依次遍历
   for(k=0;k<4;k++)
    {
      tx=x+next[k][0];//要检查的下一坐标
      ty=y+next[k][1];
      //判断是否越界
      if(tx<1||tx>n||ty<1||ty>m)
         continue;
      //判断是否为陆地 及 是否被标记
      if(a[tx][ty]>0 && book[tx][ty]==0)
       {
         sum++;
         book[tx][ty]==1; //标记该点已走过
         dfs(tx,ty,color);  //对该点着色 继续执行dfs()尝试下一点
        }
     }
   return;
 }

int main()
 {
   int i,j,num=0;
   scanf("%d %d %d",&n,&m); //输入行列数 n m    
 //读入地图数据
   for(i=1;i<=n;i++)
    for(j=1;j<=m;j++)
     scanf("%d",&a[i][j]); 

 //对每个大于0的点尝试进行dfs染色
  for(i=1;i<=n;i++)
   {
    for(j=1;j<=m;j++)
     {
      if(a[i][j]>0){
         num--;
         book[i][j] = 1;
         dfs(i,j,num);
       }
      }
    }
  //输出染色后的地图
  for(i=1;i<=n;i++)
   {
    for(j=1;j<=m;j++)
     {
       printf("%3d",a[i][j]);//3C语言中的场宽
      }
     printf("\n");
    }
   //输出小岛的个数
   printf("有%d个小岛\n",-num;/
   getchar();getchar();
   return 0;
 }
有关主函数中dfs的使用
假设从(1,1)出发,即i=1,j=1
已知a[1][1]>0,所以num–此时为-1,book[1][1]标记为1,执行dfs(1,1,-1)
观察dfs(),第一个大循环:k=0时
1.向右走) 下一步坐标(1,2),因为if判断条件a[1][2]>0&&book[1][2]==0成立,所以sum=1,book[1][2]=1(被标记),接下来对(1,2)的下一个点进行尝试,
2. 即(1,3),同理,因为if判断条件a[1][3]>0&&book[1][3]==0 成立,所以sum=2,book[1][3]=1(被标记),接下来对(1,3)的下一个点进行尝试,
3. 即(1,4),此时因为if判断条件a[1][3]>0&&book[1][3]==0 不成立,所以 回溯(因为此时k=0的dfs(1,3,-1)执行完,要继续k的循环) 即对刚刚经过的点进行其他方向(k++)的搜索,一直回溯到(1,1),对(1,1)点进入下一方向搜索:k=1(向下)
4.与上述步骤相同,一直判断到if条件不成立为止,之后再回溯 换方向
5. 对(1,1)深度搜索完成后,与其能连接到的点都被染色成 -1
6. 接下来主函数中循环进行,依然i=1,对j遍历,由上分析知(1,2),(1,3)已被标记,又因为j=4~8时,a[1][j]==0,所以直接到j=9,再进行以上循环,此时num–为-2
7. 之后的就好理解了,把i遍历完即可。

书上说这是一个 求图中独立子图的个数 的问题
此算法为Floodfill漫水填充法,也称种子填充法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值