题意: 判断图中所有黑点是否两两最多转过一个弯就能联通
分析: 深搜搜索两两是否能连通, 同时记录搜索路径的上的点, 为尽可能减少重复搜索, 每次取出没有验证过的距离较大的两点来检测是否连通
算法: 模拟, 路径搜索
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <cmath>
#include <vector>
#include <set>
#include <stack>
#include <algorithm>
//#include "myAlgorithm.h"
#define MAX 52
#define INF 1e8
#define eps 1e-5
using namespace std;
bool isConvex;
char mp[MAX][MAX];
int black[MAX*MAX][2], top = -1;
int n, m;
int dir[][2] = {{-1, 0},{1, 0},{0, -1},{0, 1}};///上下左右 0 1 2 3
bool v[MAX][MAX];
int sn, en;
bool checkedPath[MAX][MAX][MAX][MAX];
void check_path(int i, int j, int preDir, int chNum){///
if(chNum > 1)return ;
if(i == black[en][0] && j == black[en][1]){
isConvex = true;
return ;
}
v[i][j] = 1;
checkedPath[black[sn][0]][black[sn][1]][i][j] = true;
for(int k = 0; k < 4; k++){
int I = i + dir[k][0], J = j + dir[k][1];
if(I < n && I > -1 && J < m && J > -1 && mp[I][J] == 'B' && !v[I][J]){
if(k == preDir){
check_path(I, J, preDir, chNum);
}else {
check_path(I, J , k , chNum + 1);
}
}
}
v[i][j] = 0;
}
int main()
{
//freopen("in.txt", "w", stdout);
while(cin>>n>>m){
getchar();
isConvex = true;
top = -1;
for(int i = 0; i < n; i++){
gets(mp[i]);
for(int j = 0; j < m; j++){
if(mp[i][j] == 'B'){
black[++top][0] = i;
black[top][1] = j;
}
}
}///input end
//cout<<black[0][0]<<" ttt "<<black[0][1]<<endl;
for(int i = 0; i <= top; i++){
for(int j = top; j > i; j--){
if(checkedPath[black[i][0]][black[i][1]][black[j][0]][black[j][1]]){
checkedPath[black[i][0]][black[i][1]][black[j][0]][black[j][1]] = false;
continue;
}
isConvex = false;
sn = i; en = j;
//cout<<"check"<<endl;
for(int k = 0; k < 4; k++){
check_path(black[sn][0], black[sn][1], k, 0);
if(isConvex)///如果找到了
break;
}
if(!isConvex){
break;
}
}
if(!isConvex)break;
}
if(isConvex){
cout<<"YES"<<endl;
}else
cout<<"NO"<<endl;
}
return 0;
}