1. 程式人生 > 實用技巧 >題解 CF193A 【Cutting Figure】

題解 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;
	}
}