题目描述
给一 𝑛×𝑛 的字母方阵,内可能蕴含多个 yizhong
单词。单词在方阵中是沿着同一方向连续摆放的。摆放可沿着 8 个方向的任一方向,同一单词摆放时不再改变方向,单词与单词之间可以交叉,因此有可能共用字母。输出时,将不是单词的字母用 *
代替,以突出显示单词。
输入格式
第一行输入一个数 𝑛。(7≤𝑛≤100)
第二行开始输入 𝑛×𝑛 的字母矩阵。
输出格式
突出显示单词的 𝑛×𝑛 矩阵。
输入输出样例
输入 #1
7 aaaaaaa aaaaaaa aaaaaaa aaaaaaa aaaaaaa aaaaaaa aaaaaaa
输出 #1
******* ******* ******* ******* ******* ******* *******
输入 #2
8 qyizhong gydthkjy nwidghji orbzsfgz hhgrhwth zzzzzozo iwdfrgng yyyygggg
输出 #2
*yizhong gy****** n*i***** o**z**** h***h*** z****o** i*****n* y******g
这题很明显啊
肯定得用深搜
那怎么搜呢,单词的首字母是“y”,所以我们通过逐行逐列的遍历单词矩阵,如果找到“y”了,就开始深搜。我们除了定义一个存单词矩阵的数组,还要再开一个用来标记搜索路径的数组。这个数组最后会用来修改单词矩阵。
先看代码吧
#include<bits/stdc++.h>
using namespace std;
int n;//边长
bool t=0;//判断单词是否完整
char a[101][101];//单词方阵
int flag[101][101];//标记数组
int dx[8]={0,1,1,1,0,-1,-1,-1};//表示
int dy[8]={1,1,0,-1,-1,-1,0,1};//方向
//ch数组用来判断下一步的字母是否在单词里而且顺序是否对
char ch[8]={' ','y','i','z','h','o','n','g'};//判断与单词是否一致
void dfs(int x,int y,int fx,int fy,int tmp){
//x,y表示当前的坐标.fx,fy表示下一步的方向.tmp表示步数
if(a[x][y]=='g'){//如果搜索到最后一个字母是g,说明单词是完整的
flag[x][y]+=7;//g是第七个字母所以加7
t=1;//记录单词是否完整
return;
}
int xx=x+fx;//下一步
int yy=y+fy;//的坐标
if(xx<=n||xx>=1||yy<=n||yy>=1){//判断a[xx][yy]是否超出边界
if(a[xx][yy]==ch[tmp+1]){//tmp+1是下一步,ch[tmp+1]表示下一步正确的字母
//a[xx][yy]是下一步的字母
//判断顺序与字母是否对应
flag[xx][yy]+=tmp;//表示这里在单词内部
dfs(xx,yy,fx,fy,tmp+1);//继续向下搜
if(!t)flag[xx][yy]-=tmp;//如果单词不完整,则删掉来过的痕迹
}
else return;
}
else return;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++){
cin>>(a[i]+1);//(a[i]+1)可以将当前行所有字母向后移一位
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(a[i][j]=='y'){
t=0;//单词默认不完整
for(int k=0;k<8;k++){//八个方向依次搜
dfs(i,j,dx[k],dy[k],1);
}
if(t)flag[i][j]++;
//这里为了防止出现单个y没有被删去
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(!flag[i][j])a[i][j]='*';//如果没有被标记过就变成星号
cout<<a[i][j];
}
cout<<endl;
}
return 0;
}
这里为什么我要使用+=tmp而不是直接标记为1呢,tmp首先是被用来判断顺序是否真确,而且还是为了防止出现原本一串的单词背其他不完整的单词破坏。举个例子,直接记录01的形式
qyizhong 标记数组:01111111 gydthkjy 11000000 nwidghji 10100000 orbzsfgz 10010000 hhgrhwth 10001000 zzzzzozo 10000100 iwdfrgng 00000010 yyyygggg 10000001
为什么第7行第1个是0
因为当第8行第2个开始搜索时,它向左上方向没有搜到头,所以t=0,导致第26行将所有左上的全部赋值为0。用加法就不会出现这种情况,一个地方被搜索了两次,但是只错了一次,所以当前位置就不会赋值为零
阿帽的第一篇博客大功告成(其实我还有一个号,只是丢了)