シンプルで理解しやすいBFS(2)抽象BFS

以前にBFSの記事を再投稿しましたが、単純なケースはいくつかあり、元のブロガーは残りのケースを補足していませんでした。今日、たまたまBFSの質問があり、補足としてここに書きました。このシリーズは、機会があれば更新されます。

例:ロックを開く

4桁のダイヤル錠があり、各桁は1から9までの1桁です。

操作ごとに:位置の数値に1を加算するか1を減算するかを選択できます。隣接する2桁を入れ替えることもできます。(注:1を9に加算して1を取得し、1を減算して9を取得し、1桁目と4桁目は隣接していません。)

ここで、コードロックの初期状態とロック解除の最終状態については、コードロックを開くための最小ステップ数を出力する必要があります。

入力:入力
の最初の行はTで、これはテストサンプルの数を示します。

各テストサンプルには2行あります。1行目はコードロックの初期状態を表す4桁のNで、2行目はコードロックを開くためのコードを表す4桁のMです。

各テストサンプルの入力には空白行があります。

出力:
各テストサンプルについて、最小ステップ数を出力します。

サンプル入力:
2
1234
2144

1111
9999

サンプル出力:
2
4

アイデア:問題に必要な最短の手順を見ると、bfsで解決されていることがわかります。vis4次元配列を使用して、特定の4桁の数字が存在するかどうかをマークします。その間、すべての操作を個別に列挙します。

ACコード:

#include<iostream>
#include <cstring>
#include<queue>
using namespace std;

struct node{
    
    
    int a[4];
    int step;   //步数
}first,target;

char s1[4],s2[4];
int vis[11][11][11][11]; //标记某个四位数是否出现

void bfs(){
    
    
    node s, next;
    queue<node> q;

    memset(vis,0, sizeof(vis));

    s = first;
    s.step = 0;  //步数置为0
    q.push(s);
    vis[s.a[0]][s.a[1]][s.a[2]][s.a[3]] = true;

    while(!q.empty()){
    
    
        node t = q.front();  //队首元素放在t中
        q.pop();
        //如果找到目标,输出
        if(t.a[0] == target.a[0] && t.a[1] == target.a[1] && t.a[2] == target.a[2] && t.a[3] == target.a[3]){
    
    
            printf("%d\n", t.step);
            return;
        }

        for(int i = 0; i < 4; i++){
    
     //枚举四位数,都进行加一操作
            next = t;    //将t的值赋给next
            next.a[i]++;
            if(next.a[i] == 10)
                next.a[i] = 1;
            if(!vis[next.a[0]][next.a[1]][next.a[2]][next.a[3]]){
    
    
                vis[next.a[0]][next.a[1]][next.a[2]][next.a[3]] = true;
                next.step++;
                q.push(next);
            }
        }

        for(int i = 0; i < 4; i++){
    
    
            next = t;
            next.a[i]--;
            if(next.a[i] == 0)
                next.a[i] = 9;
            if(!vis[next.a[0]][next.a[1]][next.a[2]][next.a[3]]){
    
    
                vis[next.a[0]][next.a[1]][next.a[2]][next.a[3]] = true;
                next.step++;
                q.push(next);
            }
        }

        for(int i = 0; i < 3; i++){
    
     //从左到右交换相邻两个数
            next = t;
            next.a[i] = t.a[i + 1];
            next.a[i + 1] = t.a[i];
            if(!vis[next.a[0]][next.a[1]][next.a[2]][next.a[3]]){
    
    
                vis[next.a[0]][next.a[1]][next.a[2]][next.a[3]] = true;
                next.step++;
                q.push(next);
            }
        }

    }
}

int main(){
    
    
    int testNum;
    scanf("%d",&testNum);
    while (testNum--) {
    
    

        scanf("%s",s1);
        scanf("%s",s2);

        for(int i = 0; i < 4; i++){
    
     //把初始值和目标值分别赋给它们
            first.a[i] = s1[i] - '0';
            target.a[i] = s2[i] - '0';
        }
        bfs();
        if (testNum != 0) getchar();
    }
    return 0;
}

おすすめ

転載: blog.csdn.net/weixin_45024585/article/details/107722398