GYM 100971 A.Treasure Island(dfs+并查集)

来源:互联网 发布:品茗网络计划2014破解 编辑:程序博客网 时间:2024/05/18 01:09

Description
给出一张n*m的地图,点表示空地,井号表示墙,问号不确定,问是否可以把问号变成点或井号使得整张图只有一个连通块
Input
第一行两个整数n和m表示地图规模,之后一个n*m矩形表示该地图(1<=n,m<=50)
Output
如果存在唯一解则输出该唯一解,如果多解输出Ambiguous,如果无解输出Impossible
Sample Input
这里写图片描述
Sample Output
这里写图片描述
Solution
1.首先处理一些必须是#的?,即从每个点开始扫连通块,遇到问号就把问号变成点并标记,最后没有标记的问号就是一定变成#的;
2.然后判无解,即把没有处理的问号全部变成点再扫一遍连通块,用并查集维护下连通性,如果最后超过一个连通块说明无解;
3.然后判多解,即判是否存在一个问号使得将其变成#也能使得只有一个连通块,判的方法很简单,之前只有一个连通块时可以知道处于这个连通块中的点数cnt,现在开始枚举每个问号,把这个问号变成#然后开始扫连通块,如果连通块点数为cnt-1说明这个问号变成#也行,那么就多解了,否则把这个问号变成点接着去找下一个问号;
4.始终不出现多解的情况说明有唯一解
Code

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<cmath>#include<vector>#include<queue>#include<map>#include<set>#include<ctime>using namespace std;typedef long long ll;#define INF 0x3f3f3f3f#define maxn 2555char s[55][55],ss[55][55];int n,m,fa[maxn],num[maxn];void init(){    for(int i=1;i<=n*m;i++)fa[i]=i,num[i]=1;}int find(int x){    if(fa[x]==x)return x;    return fa[x]=find(fa[x]);}void unite(int x,int y){    x=find(x),y=find(y);    if(x==y)return ;    fa[y]=x;    num[x]+=num[y]; }int dx[]={-1,0,1,0};int dy[]={0,-1,0,1};int P(int x,int y){    return (x-1)*m+y;} int deal(){    init();    for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)            if(ss[i][j]=='.')                for(int k=0;k<4;k++)                {                    int ii=i+dx[k],jj=j+dy[k];                    if(ii<1||ii>n||jj<1||jj>m||ss[ii][jj]!='.')continue;                    unite(P(i,j),P(ii,jj));                }    int cnt=0,ans;    for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)            if(ss[i][j]=='.'&&fa[P(i,j)]==P(i,j))                cnt++,ans=num[P(i,j)];    if(cnt>1)return -1;    return ans;}int vis[55][55];void dfs(int x,int y){    vis[x][y]=1;    for(int k=0;k<4;k++)    {        int ii=x+dx[k],jj=y+dy[k];        if(ii<1||ii>n||jj<1||jj>m||vis[ii][jj]||ss[ii][jj]=='#')continue;        dfs(ii,jj);    }}int main(){    while(~scanf("%d%d",&n,&m))    {        for(int i=1;i<=n;i++)scanf("%s",s[i]+1);        for(int i=1;i<=n;i++)            for(int j=1;j<=m;j++)                ss[i][j]=s[i][j];        memset(vis,0,sizeof(vis));        for(int i=1;i<=n;i++)            for(int j=1;j<=m;j++)                if(!vis[i][j]&&ss[i][j]=='.')                    dfs(i,j);        for(int i=1;i<=n;i++)            for(int j=1;j<=m;j++)                if(ss[i][j]=='?'&&!vis[i][j])s[i][j]='#';        for(int i=1;i<=n;i++)            for(int j=1;j<=m;j++)            {                ss[i][j]=s[i][j];                if(s[i][j]=='?')ss[i][j]='.';            }        int cnt=deal();        if(cnt==-1)printf("Impossible\n");        else        {            int gg=0;            for(int i=1;i<=n&&!gg;i++)                for(int j=1;j<=m&&!gg;j++)                    if(s[i][j]=='?')                    {                        ss[i][j]='#';                        int temp=deal();                        if(temp==cnt-1)gg=1;                        ss[i][j]='.';                    }            if(gg)printf("Ambiguous\n");            else             {                for(int i=1;i<=n;i++)                {                    for(int j=1;j<=m;j++)                        printf("%c",ss[i][j]);                    printf("\n");                }            }        }    }    return 0;}
0 0
原创粉丝点击