gym 100971-A Treasure Island 【搜索】【暴力】

【题意】:

链接:gym100971—A Treasure Island

给你n,m。然后给你一张n*m的地图,'#' 表示水,'.' 表示陆地,‘?' 表示不确定,可能是水可能是陆地。已知,这张地图上只有一片连续的陆地,问你是否能还原这张地图,如果不可能输出Impossible,答案不唯一输出Ambiguous,答案唯一的话,将‘ ?’还原成‘ # ’或者‘ . ’。

【题解】:

教训:能暴力点就暴力点,让脑子轻松点。

首先把‘ ?’当作‘ . ',从一个陆地点开始搜索,求一下所有陆地点是否是一个联通块,如果不连通,那么必然是Impossible,同时标记搜到的每一个’ ? '和' . '为来过。

然后暴力for图中的每一个被标记为来过的‘ ?’,把这个 点暂时改成‘ # ’,然后重复刚才的搜索,判断所有陆地点是否是一个联通块,搜索完毕后改回‘ ?’,如果存在一个‘ ?’,哪怕被改成‘ # ‘,所有陆地点还是属于一个联通块,那么答案必定是Ambiguous.

不然答案唯一,将第一次搜索标记为来过的’ ? ' 改成 ‘ . ',没被标记的‘ ?‘改成 ’ # ‘。输出答案即可。

#include<bits/stdc++.h>
using namespace std;
int n,m,vis[55][55],vis2[55][55];
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
char ch[55][55];
void dfs(int i,int j)
{
    vis[i][j]=1;
    for(int g=0;g<4;g++){
        int x=i+dir[g][0];
        int y=j+dir[g][1];
        if(x>0&&x<=n&&y>0&&y<=m&&vis[x][y]==0&&ch[x][y]!='#'){
            dfs(x,y);
        }
    }
}
int solv()
{
    int cnt=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(vis[i][j]==0&&ch[i][j]=='.'){
                cnt++;
                dfs(i,j);
            }
        }
    }
    return cnt;
}
int main(void)
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%s",ch[i]+1);
    }
    int num=solv();
    if(num>1) return 0*printf("Impossible\n");
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            vis2[i][j]=vis[i][j];
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(ch[i][j]=='?'&&vis2[i][j]==1){
                ch[i][j]='#';
                memset(vis,0,sizeof(vis));
                num=solv();
                if(num==1) return 0*printf("Ambiguous\n");
                ch[i][j]='?';
            }
        }
    }
    memset(vis,0,sizeof(vis));
    solv();
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(ch[i][j]=='?'){
                if(vis[i][j]==0){
                    ch[i][j]='#';
                }
                else{
                    ch[i][j]='.';
                }
            }
        }
        printf("%s\n",ch[i]+1);
    }

    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值