题解 CF193A 【Cutting Figure】

思路:搜索


首先我们知道,最多只需要删两个点,即可满足要求。

我们所要做的就是看看能不能少删一个点。

那怎么判断呢?

就是先把这个点标为已访问过,然后另找一个涂了色的点开始搜索,如果能搜过一遍后,还有没有访问过的点,那原先这个点肯定就是所谓的 solo 之王单一解答案了。

那么我们读入数据,同时标注哪些点已经涂过色,然后在每个已经涂过点的基础上求解,如果这个涂色点能够满足单一解,那就输出 1 ,否则就输出 2 。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define F first
#define S second
using namespace std;
const int N=55;
const int dx[5]={0,1,-1,0,0},dy[5]={0,0,0,1,-1};
bool map[N][N],vis[N][N];
int n,m,num;
vector< pair<int,int> > v;
void dfs(int x,int y) {//搜索
	vis[x][y]=1;
	for(int i=1;i<=4;i++) {
		int xx=x+dx[i],yy=y+dy[i];
		if(!vis[xx][yy]&&map[xx][yy]) dfs(xx,yy);
	}
}
bool solve(int x,int y) {//求单一解
	bool opt=0;
	memset(vis,0,sizeof(vis));
	vis[x][y]=1;
	for(int i=0;i<v.size();i++) {
		if(!vis[v[i].F][v[i].S]) {
			if(opt) return 1;
			opt=1;
			dfs(v[i].F,v[i].S);
		}
	}
	return 0;
}
int main() {
	char ch;
	cin>>n>>m;
	for(int i=1; i<=n; i++) {
		for(int j=1; j<=m; j++) {
			cin>>ch;
			if(ch-'.') {
				map[i][j]=1;
				num++;
				v.push_back(make_pair(i,j));
			}
		}
	}
	if(num<=2) puts("-1");//涂色点总数小于2特判无解
	else {
		for(int i=0;i<v.size();i++) {
			if(solve(v[i].F,v[i].S)) {//求单一解
				puts("1");
				return 0;
			}
		}
		puts("2");
		return 0;
	}
}
posted @ 2020-08-03 21:05  ahawzlc  阅读(128)  评论(0编辑  收藏  举报