洛谷P1101单词方阵

题目描述

给一 n×n 的字母方阵,内可能蕴含多个 yizhong 单词。单词在方阵中是沿着同一方向连续摆放的。摆放可沿着 88 个方向的任一方向,同一单词摆放时不再改变方向,单词与单词之间可以交叉,因此有可能共用字母。输出时,将不是单词的字母用 * 代替,以突出显示单词。

输入格式

第一行输入一个数 n。(7≤n≤100)。

第二行开始输入 n×n 的字母矩阵。

输出格式

突出显示单词的 n×n 矩阵。

本题自认为方法非常巧妙,有兴趣的大佬浅浅看一下,给点优化建议。

大致思路是dfs,(建议配合代码同时食用)如下:

        需要解决的问题有三个:

  1. 如何保证后续搜索方向不改变
  2. 如何判断搜索到的字母是否符合条件
  3. 如何输出答案

        由于本题需要沿着八个方向中的其中一个直线或斜线搜索,所以我为dfs添加了一个参数dir,保证在接下来搜索中按照既定方向,于是创建了go数组。

        并且需要保证按照yizhong字母顺序对照,也就是第i个字母必须与字符串yizhong的第i个字母相等。故char一个t数组,第一个0只是起到占位作用。

        由于只输出符合题意的字符串,其余的都输出*,所以创建一个bool类型的ans数组,一旦符合,将七个位置的bool值赋值为true,方便后续输出。

#include "iostream"
using namespace std;
int go[8][2] = {{-1,0},{-1,1},{0,1},{1,1},
                 {1,0},{1,-1},{0,-1},{-1,-1}};
int n;
char t[8]={'0','y','i','z','h','o','n','g'};
char g[105][105];
bool ans[105][105];
void dfs(int x,int y,int flag,int dir){//x,y代表当前搜索的位置坐标,flag代表搜索的字母序号,flag[3]就代表当前搜索的坐标的字母需要要等于z,dir则代表了搜索的方向
    if(flag>7){//大于7说明所有的字母都搜索结束,可以用ans数组进行标记了
        dir=(dir+4)%8;//将方向逆向,因为假设是字符串是从左向右的,那必须方向逆回去才能遍历到当初的那几个坐标
        for(int i=1;i<=7;i++){
            x+=go[dir][0],y+=go[dir][1];
            ans[x][y]=true;//标记
        }
    }
    if(g[x][y]!=t[flag])return;//如果当前的字母不符合,那么直接return掉就行
    int nx=x+go[dir][0],ny=y+go[dir][1];//记录下一个搜索的坐标位置
    if((nx<1||ny<1||nx>n||ny>n)&&g[x][y]!='g')return;//如果超限,return掉,标记该位置是不是g的原因是因为,如果不加这个条件,我都遍历结束了,但是g刚好在界内,但是下一个坐标会超界,那么就会被误return掉,不理解的话,可以把这个条件去掉试试,看看输出什么
    dfs(nx,ny,flag+1,dir);//向下继续搜索
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)cin>>g[i][j];//输入已知条件的循环
    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(g[i][j]=='y'){//如果遍历到的字母是y,那么就可以后续的搜索,调用dfs函数
        for(int k=0;k<8;k++)dfs(i+go[k][0],j+go[k][1],2,k);//y已经符合所以调用dfs函数首先要搜索的是字母i
    }
    for(int i=1;i<=n;i++){//输出结果的循环
        for(int j=1;j<=n;j++){
            if(ans[i][j])cout<<g[i][j];
            else cout<<'*';
        }
        cout<<endl;
    }
}

感谢观看!

                                                                                                                        --2024/03/03  23:27

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值