题目描述
给一 n×n 的字母方阵,内可能蕴含多个 yizhong 单词。单词在方阵中是沿着同一方向连续摆放的。摆放可沿着 8 个方向的任一方向,同一单词摆放时不再改变方向,单词与单词之间可以交叉,因此有可能共用字母。输出时,将不是单词的字母用 * 代替,以突出显示单词。
输入格式
第一行输入一个数 n。(7≤n≤100)。
第二行开始输入 n×n 的字母矩阵。
输出格式
突出显示单词的 n×n 矩阵。
输入输出样例
输入
8
qyizhong
gydthkjy
nwidghji
orbzsfgz
hhgrhwth
zzzzzozo
iwdfrgng
yyyygggg
输出
*yizhong
gy******
n*i*****
o**z****
h***h***
z****o**
i*****n*
y******g
代码:
cs
#include <stdio.h>
#include <string.h>
#define maxn 102
char s[maxn][maxn];//用于存储输入的字符
int vis[maxn][maxn];//判断是否已访问
// 八个方向
int dx[] = {1, -1, 0, 0, 1, -1, -1, 1};
int dy[] = {0, 0, 1, -1, 1, 1, -1, -1};
char ans[] = "izhong"; // 用于匹配 y 之后的 6 个字符
int n;
void fun(int x, int y) {
for (int i = 0; i < 8; i++) {//有八个方向可以进行搜索
int flag = 1;//用于判断是否搜索到的7个字符符合题意,只要有一个不符合题意,就不能执行后面的if语句
int x1 = x, y1 = y;//将第一个元素y的坐标赋值给x1,x2
// 检查沿着当前方向的下 6 个字符
for (int j = 0; j < 6; j++) {
x1 += dx[i];//将该方向搜索到的字符坐标赋值给x1,y1
y1 += dy[i];
//有两个直接终止条件
// 1.越界判断,越界就说明搜索到头了,直接进行下一个方向搜索
if (x1 < 0 || x1 >= n || y1 < 0 || y1 >= n) {
flag = 0;
break;
}
//2.搜索这一个方向的时候,发现有一个字符与目标字符不符合,就说明不符合题意,就直接结束
if (s[x1][y1] != ans[j]) {
flag = 0;
break;
}
}
// 如果 7 个字符都符合(包括第一个 y),标记所有位置
//标记之后,这个一定是输出原字符的。即使有些方向这个位置不符合题意。最后输出*时,就是没有标记的字符
if (flag == 1) {
x1 = x;
y1 = y;
vis[x1][y1] = 1; // 标记起始 y
for (int j = 0; j < 6; j++) {
x1 += dx[i];
y1 += dy[i];
vis[x1][y1] = 1;
}
}
}
}
int main() {
scanf("%d", &n);
//特别要注意的是这种字符输入方式
// 读入 n 行字符串(每行长度为 n)
for (int i = 0; i < n; i++) {
scanf("%s", s[i]); // %s 自动跳过空白符,不会读入换行
}
// 初始化 vis 数组
memset(vis, 0, sizeof(vis));
// 遍历每个位置,找到 'y' 开头并尝试八个方向
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (s[i][j] == 'y') {
fun(i, j);
}
}
}
// 输出结果
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (vis[i][j]) {
printf("%c", s[i][j]);
} else {
printf("*");
}
}
printf("\n");
}
return 0;
}
上述题目的代码和之前例题的代码不一样的地方:
1.题目要求的不一样,所以要根据题意如上述定义ans[]。
2.之前是图,所以每次都从第一个位置开始,所以直接在循环后面调用函数,传入参数就是i,j。但是在这道题目里面不能从第一个位置开始,就像上面一样,要加上if条件判断。
注意!!!深搜一定要明确从哪个地方开始搜索,这道题目没有直接给出起始位置,我们就要从题意中揣测我们要搜的是什么。明确这个之后也就会定义ans[]数组的内容了。
3.可以在搜索过程中进行终止条件的书写,如果深搜到某一位置终止了,直接进行break,进行另一个方向的深搜
4.这道题目已访问过的还是能被访问,所以不和传统的深搜题目一样。但输出不同的是只输出搜索出来的符合题意的字符,那我们就需要将符合题意的字符进行标记,最后用这个标记来输出。那怎么判断是一连串的七个字符呢?就是中间没有中断。这刚好想到标志变量flag。
其他的一开始的坐标赋值,新坐标的计算都和传统的深搜一样。
我写的代码:
1.没有搞清楚初始位置,所以ans[]数组肯定就定义错了。
2.没有搞清楚要干的是什么,所以整个深搜函数就很乱。连应该输出的*也在该函数里面。坐标的赋值完全没有按照传统的深搜进行
3.在做这道题目之前一直以为一开始就要写终止条件,但我觉得还是在方向中写终止条件更好。
4.字符的输入也有点不对,这道题目刚好提供了另一种二维数组的字符输入。
下面就是我写的代码:
#include<stdio.h>
#include<string.h>
char word[]="yizhong";
int dx[]={0,1,1,1,0,-1,-1,-1};
int dy[]={1,1,0,-1,-1,-1,0,1};
void dfs(int ch[][100],int n,int m,int x,int y){
if(x<0||x>=n||y<0||y>=m){
return;
}
int i;
for(i=0;i<7;i++){
if(ch[x][y]!=word[i]){
ch[x][y]='*';
}
}
for(i=0;i<7;i++){
int nextx=x+dx[i];
int nexty=y+dy[i];
dfs(ch,visited,n,n,nextx,nexty);
}
}
int main()
{
int n;
scanf("%d",&n);
char ch[100][100];
int visited[100][100]={0};
int i,j;
for(i=0;i<n;i++){
for(j=0;j<n;j++){
scanf("%c",&ch[i][j]);
}
getchar();
}
for(i=0;i<n;i++){
for(j=0;j<n;j++){
dfs(ch,n,n,i,j);
}
}
for(i=0;i<n;i++){
for(j=0;j<n;j++){
printf("%c",ch[i][j]);
}
printf("\n");
}
return 0;
}