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 2555
char 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;
}