拆弹专家(密码BFS)

题目

拆弹专家
题目描述
外星人在地球内核种植了一颗反物质炸弹,但是把一个带密码的遥控器遗留在了地球上。
人类密码学家很快破解了该密码,但是时间不多,需要最快的时间解除该密码并解除炸弹。
程序员又来拯救世界了!
该密码由4位1~9的数字组成。
每步你可以

对任意一位数上拨或下拨。(9上拨变成1, 1上拨变成2,9下拨变成8);
把相邻的两个数字交换位置(注意,最左边的数字和最右边的数字不能直接交换);
你需要找到最少的步数输入正确的密码来解除危机!

输入说明
程序从当前路径下的data.txt文件中读取测试数据,有两行数据。
第一行4个数字,表示遥控器上当前显示的数字。
第二行4个数字表示专家破解出来的正确密码。

输出说明
解除炸弹所需要的最少步骤。

示例1
输入:

1234
2144
输出:

2
示例2
输入:

1111
9999
输出:

4

思路

  1. 直接想到暴力遍历所有步骤,但是DFS出不来,那么就用BFS。
  2. 先定义节点point,内有密码num和步骤数steps。对于每个密码先判断他是不是我们要的密码,如果不是就将它下面11次变化全部压入队列尾部,然后从队首取出下一个密码再判断。
  3. 由于有很多重复操作,我们可以设置一个visited数组,将之前出现过的数字记录一下,下次出现直接pass,因为下次出现时,其步数一定大于等于上次。

代码

#include <iostream>
#include <fstream>
#include <string>
#include <list>

using namespace std;

const int MaxSize = 1e5;
bool vis[MaxSize];

bool isVisited(string num) {
    int tmp = std::stoi(num);
    if (vis[tmp]) return true;
    vis[tmp] = true;
    return false;
}

class point {
public:
    string num;
    int steps;

    point(string num, int steps) {
        this->num = num;
        this->steps = steps;
    }
};

void BFS(string s1, string s2) {
    list<point *> list;
    point* now = new point(s1, 0);
    point* tmp = NULL;

    while (now) {
        //cout << now->steps <<": " << now->num << endl;
        if (now->num == s2) break;
        for (int i = 0; i < s1.length() - 1; i++) {
            string tnum = now->num;
            char t = tnum[i];
            tnum[i] = tnum[i + 1];
            tnum[i + 1] = t;
            if (!isVisited(tnum)) {
                tmp = new point(tnum, now->steps + 1);
                list.push_back(tmp);
            }
        }
        for (int i = 0; i < s1.length(); i++) {
            string tnum = now->num;
            tnum[i] = (tnum[i] + 1 > '9') ? '1' : (tnum[i] + 1);
            if (!isVisited(tnum)) {
                tmp = new point(tnum, now->steps + 1);
                list.push_back(tmp);
            }
        }
        for (int i = 0; i < s1.length(); i++) {
            string tnum = now->num;
            tnum[i] = (tnum[i] - 1 < '1') ? '9' : (tnum[i] - 1);
            if (!isVisited(tnum)) {
                tmp = new point(tnum, now->steps + 1);
                list.push_back(tmp);
            }
        }
        delete(now);
        now = list.front();
        list.pop_front();
    }

    cout << now->steps << endl;
    
	while (!list.empty()) {
        delete(now);
        now = list.front();
        list.pop_front();
    }
}


int main() {
    
    string s1, s2;
    fstream file("data.txt");
    file >> s1 >> s2;

    BFS(s1, s2);

    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值