Flood Fill算法(洪水灌溉算法)

有两种顺序:

①BFS(最短距离)

(涂的是陆地)

宽搜的是一圈圈的跑

伪代码:

while (队列非空)

{

    取出队头 t

    枚举 t周围的4个邻格

    if (格子是陆地, 并且格子没有吧被遍历过)

    {

        标记当前格子被用

        插入队列

    }

 }

例题: 

有一间长方形的房子,地上铺了红色、黑色两种颜色的正方形瓷砖。

你站在其中一块黑色的瓷砖上,只能向相邻(上下左右四个方向)的黑色瓷砖移动。

请写一个程序,计算你总共能够到达多少块黑色的瓷砖。

输入格式

输入包括多个数据集合。

每个数据集合的第一行是两个整数 WW 和 HH,分别表示 xx 方向和 yy 方向瓷砖的数量。

在接下来的 HH 行中,每行包括 WW 个字符。每个字符表示一块瓷砖的颜色,规则如下

1)‘.’:黑色的瓷砖;
2)‘#’:红色的瓷砖;
3)‘@’:黑色的瓷砖,并且你站在这块瓷砖上。该字符在每个数据集合中唯一出现一次。

当在一行中读入的是两个零时,表示输入结束。

输出格式

对每个数据集合,分别输出一行,显示你从初始位置出发能到达的瓷砖数(记数时包括初始位置的瓷砖)。

数据范围

1≤W,H≤201≤W,H≤20

输入样例:

6 9 
....#. 
.....# 
...... 
...... 
...... 
...... 
...... 
#@...# 
.#..#. 
0 0

输出样例:

45

代码1:(BFS) 

#include<iostream>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>

#define x first
#define y second
using namespace std;

typedef pair<int,int> PII;
 const int N=25;

 int n,m;
 char g[N][N];

 
 
 int bfs(int sx,int sy)  //宽搜写法
 {
    queue<PII> q;
    q.push({sx,sy});
    g[sx][sy]='#';
    int res=0;  //当前满足但是在while才加  
    int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
    while(q.size())
    {
        res++;
        PII t=q.front();
        q.pop();
        for(int i=0;i<4;i++)
        {
            int x1=t.x+dx[i],y1=t.y+dy[i];
            if(x1<0 || x1>=n || y1<0 || y1>=m || g[x1][y1]!='.') continue;
            g[x1][y1]='#';
            q.push({x1,y1});
        }
    }
    return res;
 }



int main()
{
   
    while(cin>>m>>n,n||m)
    {
         for(int i=0;i<n;i++) scanf("%s",g[i]);
         int x1,y1;
         for(int i=0;i<n;i++)
          for(int j=0;j<m;j++)
            if(g[i][j]=='@')
             {
                 x1=i;
                 y1=j;
             }
    cout<<bfs(x1,y1)<<endl;
    }
    return 0;
}

②DFS(可能 爆栈 (1M由于递归可能会,256一般不会),更方便)

(每个格子都按照上右下左的顺序看,只要当在某一个方向第一次碰到符合的就到这个格子继续重复) 

dfs(x,y)
{
    将(x,y)标记为已走
    枚举(x,y)的4个邻点
    if 邻点可走
    dfs(此点)
}

题目:同上

代码:

#include<iostream>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>

#define x first
#define y second
using namespace std;

typedef pair<int,int> PII;
 const int N=25;

 int n,m;
 char g[N][N];
 int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
 int dfs(int x1,int y1)  //深搜写法
 {
     int res=1;  //当前可以
     g[x1][y1]='#';
     for(int i=0;i<4;i++)
     {
         
         int a=x1+dx[i],b=y1+dy[i];
         if(a>=0 &&a<n&& b>=0 && b<m &&g[a][b]=='.')  //符合条件
            res+=dfs(a,b);  //不能用+1,要回溯
     }
        return res;
 }
 
 


int main()
{
   
    while(cin>>m>>n,n||m)
    {
         for(int i=0;i<n;i++) scanf("%s",g[i]);
         int x1,y1;
         for(int i=0;i<n;i++)
          for(int j=0;j<m;j++)
            if(g[i][j]=='@')
             {
                 x1=i;
                 y1=j;
             }
    cout<<dfs(x1,y1)<<endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值