HDU 3839Ancient Messages(BFS + 连通块,判图形)

本文深入探讨了如何通过图结构分析复杂图形,并详细解释了相关算法的应用过程。包括了图的遍历、连通性判断、颜色标记等关键步骤,以及如何利用这些原理解决实际问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:给你一张图, 输出图里包涵的图形。
题目给出的图所围成的连通的白色块是不一样的,根据这个来判断

#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#include<set>
#include<stack>
#define cl(a,b) memset(a,b,sizeof(a));
#define LL long long
#define P pair<int,int>
#define X first
#define Y second
#define out(x) cout<<x<<endl;
using namespace std;
const int maxn=950;
const int inf=9999999;
char convers[16][5]={"0000","0001","0010","0011","0100",
"0101","0110","0111","1000","1001","1010","1011",
"1100","1101","1110","1111"};
char tu[]="WAKJSD";
int n,m;
int dir[][2]={{0,1},{1,0},{-1,0},{0,-1}};

char a[maxn][maxn];//输入的图转化为01二进制构成的图
char tmp[maxn];
char myans[maxn];

int color[maxn][maxn];//每个点的标志颜色
bool vis[maxn][maxn];//访问标记

void bfs_color(int x,int y,int num,char aim){
//外围的白色编号-1,被黑色围住的白色部分从-2开始编号,黑色图案从1开始依次编号
    queue<P> q;
    q.push(P(x,y));
    vis[x][y]=true;
    color[x][y]=num;
    while(!q.empty()){
        P tmp=q.front();q.pop();
        for(int i=0;i<4;i++){
            P s=tmp;
            int xx=s.X+dir[i][0];
            int yy=s.Y+dir[i][1];
            if(xx<0||xx>n||yy<0||yy>m||vis[xx][yy]||a[xx][yy]!=aim)continue;
            vis[xx][yy]=true;
            color[xx][yy]=num;
            q.push(P(xx,yy));
        }
    }
}
bool used[maxn][maxn];
int bfs(int x,int y,int num){
    set<int> myset;
    queue<P> q;
    q.push(P(x,y));
    used[x][y]=true;
    while(!q.empty()){
        P tmp=q.front();q.pop();
        for(int i=0;i<4;i++){
            P s=tmp;
            s.X+=dir[i][0];
            s.Y+=dir[i][1];
            if(s.X<0||s.X>n||s.Y<0||s.Y>m||used[s.X][s.Y])continue;
            if(a[s.X][s.Y]=='1'&&color[s.X][s.Y]==num){
                used[s.X][s.Y]=true;
                q.push(s);
            }
            else if(a[s.X][s.Y]=='0'&&color[s.X][s.Y]<=-2){
                myset.insert(color[s.X][s.Y]);
            }
        }
    }
    return myset.size();
}
int main(){
    int cas=1;
    while(~scanf("%d%d",&n,&m)&&(n||m)){
        cl(a,'\0');//在图的周围加上一圈,便于下面的计数
        for(int i=0;i<=n+1;i++)a[i][0]=a[i][m*4+1]='0';
        for(int i=0;i<=m*4+1;i++)a[0][i]=a[n+1][i]='0';

        for(int i=1;i<=n;i++){
            scanf("%s",tmp);
            for(int j=0;j<m;j++){
                if(tmp[j]>='0'&&tmp[j]<='9'){
                    int index=tmp[j]-'0';
                    strcat(a[i],convers[index]);
                }
                else {
                    int index=tmp[j]-'a'+10;
                    strcat(a[i],convers[index]);
                }
            }
        }

        for(int i=0;i<=n+1;i++)a[i][0]=a[i][m*4+1]='0';
        for(int i=0;i<=m*4+1;i++)a[0][i]=a[n+1][i]='0';
        m*=4;m+=1;n+=1;

        cl(color,0);
        cl(vis,false);
        bfs_color(0,0,-1,'0');//外围的0染成-1,区别于被黑色包围的内部的白色块
        int num=1;
        for(int i=0;i<=n;i++){
            for(int j=0;j<=m;j++)if(a[i][j]=='1'&&!vis[i][j]){
                bfs_color(i,j,num,'1');num++;//黑色块的编号
            }
        }
        int num2=-2;
        for(int i=0;i<=n;i++){
            for(int j=0;j<=m;j++)if(a[i][j]=='0'&&!vis[i][j]){
                bfs_color(i,j,num2,'0');num2--;//黑色包涵的白色块编号
            }
        }
        cl(used,false);
        int t=0;
        for(int i=0;i<=n;i++){
            for(int j=0;j<=m;j++)if(!used[i][j]&&color[i][j]>=1){
                int x=bfs(i,j,color[i][j]);//搜出黑色块里的白色块个数
                myans[t++]=tu[x];
            }
        }
        myans[t]='\0';
        sort(myans,myans+t);
        printf("Case %d: %s\n",cas++,myans);
    }
    return 0;
}

/*
3 2
ff
f0
ff
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值