题目链接
链接: 1107. 魔板
题目描述
输入样例:
2 6 8 4 5 7 3 1
输出样例:
7
BCABCCB
解题思路
首先想到bfs,这道题和八数码很像,在状态表示上不同
初始状态12345678表示成魔板是这样的
1234
8765
那操作的时候就可以使用数组模拟
类似于操作A
操作之后魔板会变成
8765
1234
那么他对应的字符串就是 8 7 6 5 4 3 2 1那么这里第一个元素8在之前的字符串中的下标为4,依此类推,7在原字符串中的下标是5,那么得出下面三种操作的代码
string get(int i, string s)
{
string ss;
switch (i) {
case 0: ss = { s[4],s[5],s[6],s[7],s[0],s[1],s[2],s[3] }; break;
case 1: ss = { s[3],s[0],s[1],s[2],s[7],s[4],s[5],s[6] }; break;
case 2: ss = { s[0],s[5],s[1],s[3],s[4],s[6],s[2],s[7] }; break;
}
return ss;
}
之后就是使用最小步数模型,使用哈希表存储上一个状态和上一个状态的操作
最后利用dfs输出操作路径
代码实现
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
#define x first
#define y second
using namespace std;
char a[10];
string end_state;
string start_state = "12348765";
string get(int i, string s)
{
string ss;
switch (i) {
case 0: ss = { s[4],s[5],s[6],s[7],s[0],s[1],s[2],s[3] }; break;
case 1: ss = { s[3],s[0],s[1],s[2],s[7],s[4],s[5],s[6] }; break;
case 2: ss = { s[0],s[5],s[1],s[3],s[4],s[6],s[2],s[7] }; break;
}
return ss;
}
typedef map<string, pair<char, string>> MSP;//当前状态,上一步通过哪一个操作变成下一个状态,上一个状态
map<string, int> dist;
MSP pre;
int bfs()
{
queue<string> q;
q.push(start_state);
dist[start_state] = 0;
while (!q.empty())
{
string t = q.front();
q.pop();
if (t == end_state) return dist[t];
for (int i = 0; i < 3; i++)
{
string xx = get(i, t);
if (!dist.count(xx))
{
dist[xx] = dist[t] + 1;
pre[xx] = { 'A' + i, t };
q.push(xx);
}
}
}
}
void dfs(string s)
{
if (s == start_state)
{
cout << pre[s].x;
return;
}
dfs(pre[s].y);
cout << pre[s].x;
}
int main()
{
for (int i = 1; i <= 8; i++) cin >> a[i];
reverse(a + 5, a + 8 + 1);
for (int i = 1; i <= 8; i++) end_state.push_back(a[i]);
cout << bfs() << endl;
dfs(end_state);
return 0;
}
总结
BFS最小步数模型