#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 ; }
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做的,这个程序不仅适用于只能改变一次方向,任意次方向均能解决。
具体程序如下: