Foold Fill 算法

能在线性时间内求出图中的连通块数量

eg 1:acwing 1098
城堡问题

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int N=55,M=N*N;
int n,m;
#define x first
#define y second
int g[N][N];
bool st[N][N];
pii q[M];
int bfs(int sx,int sy)
{
    int dx[]={0,-1,0,1},dy[]={-1,0,1,0};
    int maxs=0;
    int hh=0,tt=0;
    
    q[tt]={sx,sy};
    st[sx][sy]=true;
    while(tt>=hh)
    {
        auto A=q[hh++];
        maxs++;
        
        for(int i=0;i<4;i++)
        {
            int a=A.x+dx[i],b=A.y+dy[i];
            if(a<0 || a>=n || b<0 || b>=m) continue;
            if(st[a][b]) continue;
            if(g[A.x][A.y] >> i & 1) continue;//判断是不是有墙  看的是g中二进制数的第i位是不是1
            q[++tt] = {a,b};
            st[a][b]=true;
        }
    }
    
    return maxs;
    
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            cin>>g[i][j];
        
    
    int cnt=0,maxs=0;
    
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            if(!st[i][j])
            {
                cnt++;
                maxs=max(maxs,bfs(i,j));
            }
            
    cout<<cnt<<endl;
    cout<<maxs<<endl;
  
    return 0;
             
}

eg2: acwing 1106
山峰山谷

#include<bits/stdc++.h>
using namespace std;

#define x first
#define y second

typedef pair<int,int> pii;

const int N = 1010,M=N*N;
int h[N][N];
int n;
bool st[N][N];
pii q[M];

void bfs(int sx,int sy,bool& has_higher,bool& has_lower)
{
    int hh=0,tt=0;
    q[0]={sx,sy};
    st[sx][sy]=1;
    
    while(tt>=hh)
    {
        auto t=q[hh++];
        
        for(int i=t.x-1;i<=t.x+1;i++)
            for(int j=t.y-1;j<=t.y+1;j++)
            {   
                //if(st[i][j]) continue  不能写这句 因为在边界时 就算st==1
                // 也需要考虑峰谷的问题
                if(i<0||i>=n||j<0||j>=n) continue;
                if((h[i][j]!=h[t.x][t.y]))
                {
                    if(h[i][j]>h[t.x][t.y]) has_higher=1;
                    else has_lower=1;
                }
                else if(!st[i][j])
                {
                    q[++tt] = {i,j};
                    st[i][j]=true;
                }
                
            }
    }
}
int main()
{
    cin>>n;
    
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++) cin>>h[i][j];
        
    int peak=0,valley=0;
    
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            if(!st[i][j])
            {
                bool has_higher=false,has_lower=false;
                bfs(i,j,has_higher,has_lower);
                
                if(!has_higher) peak++;
                if(!has_lower) valley++;
            }
            
    cout<<peak<<" "<<valley<<endl;
    
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值