#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int n ,m ;
char s[55][55] ;
int vis[55][55] ;
int X[4] = {0,0,1,-1} ;
int Y[4] = {1,-1,0,0} ;
int cango(int x, int y)
{
if(x >= 0 && x < n && y >= 0 && y < m && s[x][y] == 'B')
return 1 ;
return 0 ;
}
void dfs(int x , int y , int cnt , int ben) // cnt是标志变量,具体应用如下,ben 是为了记录上一次的方向
{
vis[x][y] = 1 ;
int k ;
for(k = 0 ; k < 4 ; k ++)
{
int tx , ty ;
tx = x + X[k] ;
ty = y + Y[k] ;
int tben , tcnt ;
if(cango(tx , ty))
{
if(cnt == 0) // cnt == 0 代表起点
{
ben = k ;
tcnt = cnt + 1 ;
tben = ben ;
dfs(tx,ty,tcnt,tben) ;
}
else if(cnt == 1 && k != ben) // 此种情况是第一次改变方向
{
tben = k ;
tcnt = cnt + 1 ;
dfs(tx,ty,tcnt,tben) ;
}
else if(cnt == 2 && k != ben) // 此种情况 是 第二次 改变方向
{
continue ;
}
else if(cnt == 1 && k == ben) // 此种情况是来到当前点的方向与上一次的方向相同,此前“还未改变过“方向
{
tben = k ;
tcnt = cnt ;
dfs(tx,ty,tcnt,tben) ;
}
else if (cnt == 2 && k == ben) // 此种情况是来到当前点的方向与上一次的方向相同,此前“已经改变过一次”方向
{
tben = k ;
tcnt = cnt ;
dfs(tx,ty,tcnt,tben) ;
}
}
}
}
int main()
{
while (scanf("%d%d",&n,&m) != EOF)
{
int i ;
int j ;
for(i = 0 ; i < n ; i ++)
{
for(j = 0 ; j < m ; j ++)
{
cin >> s[i][j] ;
}
}
int pan = 0 ;
for(i = 0 ; i < n ; i ++)
{
for(j = 0 ; j < m ; j ++)
{
if(s[i][j] == 'B')
{
memset(vis , 0 , sizeof(vis)) ;
dfs(i,j,0,-1) ;
int i2 , j2 ;
for(i2 = 0 ; i2 < n ; i2 ++)
{
for(j2 = 0 ; j2 < m ; j2 ++)
{
if(s[i2][j2] == 'B' && !vis[i2][j2])
{
pan = 1;
break ;
}
}
if(pan == 1)
break ;
}
}
if(pan == 1)
break ;
}
if(pan == 1)
break ;
}
if(pan == 1)
printf("NO\n") ;
else
printf("YES\n") ;
}
return 0 ;
}
这次周赛的A、F、H题都是比较水的题, 不作详细讲解,C题是简单的并查集问题,也不再敖述,下面着重讲一讲B题和G题:
B题 :
题目大意 : 给你几个字符串 ,让你找出这些字符串中都未出现过的字符串,将字典序最小的输出。
程序如下 :
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<vector>
#include<algorithm>
using namespace std;
struct pp
{
int x ;
char s[35] ;
} p[35] ;
char zimu[30]; // 装 26 个 英文字母
char A[35] ; // 定义源字符串数组
int n ;
int pan ;
int n2 ;
int res ;
void dfs(int cur) // 用dfs来枚举子串
{
if(res == 1)
return ;
int i;
for(i = 0 ; i < 26 ; i ++)
{
A[cur] = zimu[i] ;
pan = 0 ;
if(cur == n2 - 1)
{
for(int j = 0 ; j < n ; j ++)
{
char *k ;
k = strstr(p[j].s,A) ; // 在A中查找子串
if(k)
{
pan = 1 ;
break ;
}
}
}
if(cur == n2 - 1 && pan == 0)
{
cout << A << endl ;
res = 1 ;
return ;
}
else if(cur < n2 - 1)
{
dfs(cur + 1) ;
A[cur] = '\0' ;
}
}
}
int main()
{
int i ;
for(i = 0; i < 26 ; i ++)
{
zimu[i] = 'a' + i ;
}
while (scanf("%d",&n) != EOF)
{
memset(A,'\0',sizeof(A)) ;
for(i = 0 ; i < n ; i ++)
{
scanf("%s",p[i].s) ;
p[i].x = 0 ;
}
res = 0 ;
int i ;
for(i = 1 ; i < 35 ; i ++) // 根据子串的长度来枚举子串
{
if(!res)
{
n2 = i;
dfs(0) ;
}
else
{
break ;
}
}
}
return 0 ;
}
G题 :
题目大意: 给你一个 n * m 的网格,每个小格不是白色就是黑色,问:对网格中的任意两个黑色小格,设为X和Y, X能不能通过其它黑色小网格到达Y(注意:途中只能改变一次方向) ?
思路:这道题我使用DFS做的,这个程序不仅适用于只能改变一次方向,任意次方向均能解决。
具体程序如下: