简单易懂BFS(二)抽象BFS

之前转发过一篇BFS的文章,但是只有一些简单的情况,剩余的一些情况原博主没有进行补充。碰巧我今天刷题刷到了一个BFS的题目,写在这里,做一个补充。如果有机会这个系列还会更新。

例题:Open the Lock

有一个密码锁,由四位的数字组成,每一位的数字是从1到9 中的一个。

对于每一次操作:你可以选择对一个位置上的数字 进行加1或者减1操作。也可以选择交换相邻两位的数字。(注意:对9加1得到的是1,对1减1后得到的是9,且第1位和第4位数字不相邻。)

现在给密码锁的初始状态,以及开锁的最终状态,要求输出打开密码锁的最小步数。

Input:
输入的第一行是T,表示测试样例的数目。

每个测试样例有两行,第一行是一个四位数N,表示密码锁的初始状态,第二行是一个四位数M,表示打开密码锁的密码。

每个测试样例的输入隔有一个空行。

Output:
对于每个测试样例,输出最小步数。

Sample Input:
2
1234
2144

1111
9999

Sample Output:
2
4

思路:看见题目要求最短步骤就可以知道用bfs来解决了,用vis四维数组来标记某个四位数是否存在过;在while里面,分别枚举所有的操作

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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值