题目
拆弹专家
题目描述
外星人在地球内核种植了一颗反物质炸弹,但是把一个带密码的遥控器遗留在了地球上。
人类密码学家很快破解了该密码,但是时间不多,需要最快的时间解除该密码并解除炸弹。
程序员又来拯救世界了!
该密码由4位1~9的数字组成。
每步你可以
对任意一位数上拨或下拨。(9上拨变成1, 1上拨变成2,9下拨变成8);
把相邻的两个数字交换位置(注意,最左边的数字和最右边的数字不能直接交换);
你需要找到最少的步数输入正确的密码来解除危机!
输入说明
程序从当前路径下的data.txt文件中读取测试数据,有两行数据。
第一行4个数字,表示遥控器上当前显示的数字。
第二行4个数字表示专家破解出来的正确密码。
输出说明
解除炸弹所需要的最少步骤。
示例1
输入:
1234
2144
输出:
2
示例2
输入:
1111
9999
输出:
4
思路
- 直接想到暴力遍历所有步骤,但是DFS出不来,那么就用BFS。
- 先定义节点point,内有密码num和步骤数steps。对于每个密码先判断他是不是我们要的密码,如果不是就将它下面11次变化全部压入队列尾部,然后从队首取出下一个密码再判断。
- 由于有很多重复操作,我们可以设置一个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;
}