GYM Samara16 A Treasure Island 暴力

题意:n*m的地图,'#'表示障碍, '.'表示land, '?'表示待定. 可以上下左右移动.
问是否能将地图上所有的'?'变为'.'或者'#' 使得地图上只有一个联通分量.
n,m<=50. 无解输出impossible ,若有多解 则输出ambiguous. 只有一解输出变化后的地图.


先把所有的'?'都变为'.' 还是有多少个联通分量时
如果有某个个联通分量全部都为'?则把该摧毁该连通分量,直到联通分量个数为1为止.
若此时联通分量个数还是>1则无解.


现在只有一个联通分量 
若把'?'的某个集合{p1,p2,..pk] 由'.'变为'#'时联通分量个数还是1.那么单独把某个pi变为'#',此时联通分量个数还是1.

枚举把某个'?'由'.'变为'#' 若此时联通分量个数还是1,则有多解 O(n^2 m^2).

#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> ii;
const int N=55;
char s[N][N];
int n,m,vis[N][N],mp[N*N],num=0,tot=0;
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};
vector<ii> a;
void dfs(int x,int y)
{
	vis[x][y]=1;
	tot++;
	if(s[x][y]=='?')
		num++;
	for(int i=0;i<4;i++)
	{
		int a=x+dx[i],b=y+dy[i];
		if(a>=1&&a<=n&&b>=1&&b<=m&&(!vis[a][b])&&s[a][b]!='#')
			dfs(a,b);
	}
}
void fun(int x,int y)
{
	vis[x][y]=1;
	s[x][y]='#';
//	cout<<x<<' '<<y<<endl;
	for(int i=0;i<4;i++)
	{
		int a=x+dx[i],b=y+dy[i];
		if(a>=1&&a<=n&&b>=1&&b<=m&&(!vis[a][b])&&s[a][b]=='?')
			fun(a,b);
	}
}
int check()
{
	int cnt=0;
	memset(vis,0,sizeof(vis));
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			if(s[i][j]!='#'&&!vis[i][j])
				dfs(i,j),cnt++;
	return cnt;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",s[i]+1);
		for(int j=1;j<=m;j++)
			if(s[i][j]=='?')
				a.push_back(ii(i,j));		
	}
	int p=0;
	if(check()>1)
	{
		for(int i=0;i<a.size();i++)
		{
			if(s[a[i].first][a[i].second]=='#')
				continue; 
			num=tot=0;	
			memset(vis,0,sizeof(vis));
			dfs(a[i].first,a[i].second);
			//cout<<i<<' '<<num<<' '<<tot<<endl;
			if(num==tot)
			{
				memset(vis,0,sizeof(vis));
				fun(a[i].first,a[i].second);
			}
		}
		if(check()>1)
		{
			puts("Impossible");
			return 0;
		}
	}
	bool flag=true;
	for(int i=p;i<a.size();i++)
	{
		int x=a[i].first,y=a[i].second;
		if(s[x][y]=='#')	continue;
		s[x][y]='#';
		if(check()==1)
			flag=false;
		s[x][y]='.';
	}
	if(!flag)
		puts("Ambiguous");
	else
		for(int i=1;i<=n;i++)
			printf("%s\n",s[i]+1);
		
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值