Date:2019/10/27
这道题还算做的可以,一看题面就知道是一道最最最普通的DFS
所以递归位置,并注意打标记,看跑完一次后次数有没有
c
n
t
≥
4
cnt\geq 4
cnt≥4就可以了
坑点
- 字符地图的输入,字符地图输入需要判定不是换行符,如果不判定的话会很糟糕
- 每次递归时,如果满足条件就直接结束整个程序,不要继续递归了
因为有一个点50*50的图全是A
AC code[DFS]
//Author:PhilFan;
#include<bits/stdc++.h>
using namespace std;
int n,m,tot;
int movx[4]={0,1,0,-1};
int movy[4]={1,0,-1,0};//移动
int mapx[55][55];//地图
int fx,fy;
bool vis[55][55];
//-----------------------------------------------------------------------------
void dfs(int x,int y,int cnt){
if(x == fx && y == fy && cnt != 0){ //跑完一遍并且不是一开始就跑完
if(cnt >= 4){ //如果次数大于4,就输出并直接退出
cout<<"Yes";
exit(0);
}
}
int xx,yy;
for(int i = 0; i <= 3;i++){ //跑地图写法,比较经典,详见迷宫
xx = x+movx[i];
yy = y+movy[i];
if(xx>=1 && xx <= n && yy >= 1 && yy <= m && vis[xx][yy]==0 && mapx[xx][yy] == mapx[x][y]){
vis[xx][yy] = 1;
dfs(xx,yy,cnt+1);
vis[xx][yy] = 0;
}
}
}
int main()
{
scanf("%d %d",&n,&m);
for(int i = 1; i <= n;i++){ 字符地图输入,恶心心
getchar();
for(int j = 1; j <= m;j++){
char a;
a = getchar();
while(a < 'A' || a >'Z'){a = getchar();}
mapx[i][j] = a - 'A';
}
}
for(int i = 1; i <= n;i++){
for(int j = 1; j <= m;j++){
fx = i,fy = j;
memset(vis,0,sizeof(vis));
dfs(i,j,0);
}
}
cout<<"No";
return 0;
}
联通图的写法(Form zzc)
主要思路:为上下左右搜索 + 打标记 未走过的地方为0
以一个之前从未dfs过的字母为开头进行搜索,与其联通的所有字母全部搜索后若无回到起点的字母,则其中的所有联通的字母全部不成立,之后不进行搜索
#include<bits/stdc++.h>
using namespace std;
const int maxn = 60;
int n,m,xx[6]={0,1,-1,0,0},yy[6]={0,0,0,1,-1},a_x,a_y;
char f[maxn][maxn];
int vis[maxn][maxn];//仍代表标记 方式改变 -1代表走过 0 为未走,搜索过程中以1……n代表走的步数
void dfs(int x,int y,int k,char j,int num){
if(num >= 4){
for(int i = 1; i <= 4; i++){
if(vis[x + xx[i]][y + yy[i]] == -1 || vis[x + xx[i]][y + yy[i]] == 0 )continue;
if(vis[x][y] - vis[x + xx[i]][y + yy[i]] >= 3){
printf("Yes");//一旦出现回路立刻输出Yes 并结束整个程序,可减少运行次数
exit(0);
}
}
}
for(int i = 1; i <= 4; i++){
if(vis[x + xx[i]][y + yy[i]] || x + xx[i] > n || x + xx[i] < 0 || y + yy[i] == m || y + yy[i] < 0)continue;
if(f[x + xx[i]][y + yy[i]] == j){
vis[x + xx[i]][y + yy[i]] = k + 1;
dfs(x + xx[i],y + yy[i],k + 1,j,num + 1);//这里k变成k + 1
vis[x + xx[i]][y + yy[i]] = 0;
}
}
vis[x][y] = -1;//标记为-1
return ;
}
int main(){
scanf("%d%d",&n,&m);
for(int i = 1; i <= n;i++)
scanf("%s",f[i]);
int cnt = 0;
for(int i = 1; i <= n ;i++){
for(int j = 0; j < m;j++){
if(vis[i][j] == -1) continue;
a_x = i;a_y = j;
vis[i][j] = 1;//起始点为1
dfs(i,j,1,f[i][j],1);
}
}
printf("No");
return 0;
}
老师的写法(From ivy_uu)
莫名奇妙快一点~
这!
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int n,m,k;
const int N=64;
char arr[N][N];
bool flag = false;
bool visit[N][N];
int dirx[]={1,0,-1,0};
int diry[]={0,1,0,-1};
void dfs(int i,int j,int pi,int pj){
if(visit[i][j]){
flag = true;
return;
}
visit[i][j]=true;
for(int k=0;k<4;k++){
int nextx = i+dirx[k];
int nexty = j+diry[k];
if(nextx>=0&&nextx<n&&nexty>=0&&nexty<m&&arr[i][j]==arr[nextx][nexty]){
if(!(nextx==pi&&nexty==pj)){
dfs(nextx,nexty,i,j);
}
}
}
}
int main() {
while(scanf("%d%d", &n, &m)==2){
flag = false;
for(int i=0;i<n;i++) scanf("%s", arr[i]);
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
memset(visit,0,sizeof(visit));
dfs(i,j,-1,-1);
if(flag){
cout<<"Yes"<<endl;
break;
}
}
if(flag) break;
}
if(!flag) cout<<"No"<<endl;
}
return 0;
}