​单词方阵 - 洛谷​

一、题目信息

1、题目链接:单词方阵 - 洛谷

二、题目分析

1、分析:

  • 我们需要识别出字母方阵中连续、直线排列的”yizhong“串。具体地,遍历字母方阵的字母,从‘y’开始,我们从8个方向选定一个方向沿直线走,边走边判断当前字母与”yizhong“串中的对应下标字母是否相等
  • 我们需要对属于这样的串的字符和不属于这样的串的字母按某种方式做区分,在输出时据此判断是输出原字符还是输出‘*’

2、思路:

  • 当我们(按序)识别出”yizhong“串后,需要记录每个字符的位置信息,暂时想到两种方式:
    • 递归,递归结束时根据结果(是”yizhong“串或不是)判断是否记录当前字符的位置
    • 在沿直线匹配”yizhong“串时用一个分表记录遍历的字符的位置,当遍历到最后发现是”yizhong“串时分表就可以写入总表,最后打印时用到总表;否则遗弃分表
  • 打印:遍历字符方阵,仅当前字符的位置是有记录的(意味着当前字符是”yizhong“串的一部分)打印原字符,否则打印‘*’

三、代码

1、递归

#include<iostream>
#include<set>
using namespace std;

//根据方向获取下一步的坐标
void forward(string direction,int& x,int& y){
    if(direction=="lefttop"){
        x--;y--;
    }else if(direction=="left"){
        x--;
    }
    else if(direction=="leftdown"){
        x--;y++;
    }
    else if(direction=="top"){
        y--;
    }
    else if(direction=="down"){
        y++;
    }
    else if(direction=="righttop"){
        x++;y--;
    }
    else if(direction=="right"){
        x++;
    }
    else if(direction=="rightdown"){
        x++;y++;
    }
}

int n;
bool dfs(string& target,int index,string arr[],set<pair<int,int>>& s,string& direction,int x,int y){
    if(index>=target.size()) return true;  //是"yizhong"串
    if(x>=n||y>=n||x<0||y<0) return false;   //超出界外
    if(target[index]!=arr[y][x]) return false;  //字母不匹配,不是“yizhong”串
    int now_x=x,now_y=y;
    forward(direction,x,y);   //下一步
    if(dfs(target,index+1,arr,s,direction,x,y)){
        s.insert({now_x,now_y});
        return true;
    }else{
        return false;
    }
}

int main(){
    cin>>n;
    string arr[n],target="yizhong";
    for(int i=0;i<n;i++){
        cin>>arr[i];
    }
    string directions[8]={"lefttop","top","righttop","right","rightdown","down","leftdown","left"};
    string direction;
    set<pair<int,int>> s;
    for(int y=0;y<n;y++){
        for(int x=0;x<n;x++){
            for(int i=0;i<8;i++){  //遍历8个方向
                direction=directions[i];
                dfs(target,0,arr,s,direction,x,y);
            }
        }
    }
    for(int y=0;y<n;y++){
        for(int x=0;x<n;x++){
            if(s.count({x,y})>0){
                cout<<arr[y][x];
            }else{
                cout<<'*';
            }
        }
        cout<<endl;
    }
    return 0;
}

2、非递归

#include<iostream>
#include<set>
using namespace std;

//根据方向获取下一步的坐标
void forward(string direction,int& x,int& y){
    if(direction=="lefttop"){
        x--;y--;
    }else if(direction=="left"){
        x--;
    }
    else if(direction=="leftdown"){
        x--;y++;
    }
    else if(direction=="top"){
        y--;
    }
    else if(direction=="down"){
        y++;
    }
    else if(direction=="righttop"){
        x++;y--;
    }
    else if(direction=="right"){
        x++;
    }
    else if(direction=="rightdown"){
        x++;y++;
    }
}

int main(){
    int n;cin>>n;
    string arr[n],target="yizhong";
    for(int i=0;i<n;i++){
        cin>>arr[i];
    }
    
    string directions[8]={"lefttop","top","righttop","right","rightdown","down","leftdown","left"};
    string direction;
    set<pair<int,int>> s;     //存储属于“yizhong”串的字母的位置
    int index;
    for(int y=0;y<n;y++){
        for(int x=0;x<n;x++){
            for(int i=0;i<8;i++){   //遍历8个方向
                int now_x=x,now_y=y;
                direction=directions[i];
                set<pair<int,int>> temp;  //存储遍历的字母的位置
                for(index=0;index<7;index++){
                    if(now_x>=0&&now_y>=0&&now_x<n&&now_y<n&&target[index]==arr[now_y][now_x]){
                        temp.insert({now_x,now_y});
                        forward(direction,now_x,now_y);
                    }else{
                        break;
                    }
                }
                if(index==7){ //是“yizhong”串
                    s.insert(temp.begin(),temp.end());
                }
            }
        }
    }
    for(int y=0;y<n;y++){
        for(int x=0;x<n;x++){
            if(s.count({x,y})>0){
                cout<<arr[y][x];
            }else{
                cout<<'*';
            }
        }
        cout<<endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值