思路:BFS
是一道比较麻烦的BFS搜索题。
这一道题的难点就在于你怎么对于这行数字进行状态压缩。意思就是把这个数字转化成你能够处理的状态。
讲一下具体的代码思路:
首先,我们习惯于用字符串对于数字进行转化,一开始我们令数字变成字符串,方便我们在之后BFS遍历时使用。
然后,我们可以看到,定义了一个数组cunchu,这个其实就是状态压缩的还原数组,也就是把里面的字符串变成二维数组的形式,也就是题目中说的那种形式。这样方便我们进行题目中的A,B,C操作,可以看到,我们在刚开始的预处理中,首先把字符串变成了cunchu数组也就是sets函数,然后再cunchu数组的基础上进行A,B,C的操作,至于A,B,C操作就不详细讲了,因为是语言基础必练的技巧。
我们操作完之后,需要把这个二维数组再变成字符串,我们就需要压缩了,我们刚刚怎么还原的,那么就倒着来压缩回去。这样就得到了新的字符串get()。
好了,预处理结束之后,我们进入BFS的操作。
前面的pus字符串就和入队坐标一样的操作,至于dist是什么,dist是记录我们的字符串有没有被变换过的数组,也就是相当于在普通问题中走没走过这个路的一种变换。总之就是标记路走没走过。
然后,我们就直接循环了。但是,我们以往的习惯是对于dx,dy进行判断周围,这里需要怎么做呢?来了,m数组定义了,我们取出来队头的字符串,然后有上面三种操作可以选,这样的话就符合我们以前的习惯进行BFS遍历了。
接着就是判断变换之后的字符串有没有遍历过了,没有遍历过,我们就让这个字符串的dist在原先过来的字符串的基础上+1,这样相当于走了一步。
大家会发现,又定义了pre这个东西,这是个啥?也是个哈希表。因为题目中明确说明了我们需要存储字典序最小的一条变化操作,这个东西就是用来存储操作字符的。那么是什么意思呢?这个代表:现在变换之后的字符是由上一个字符经过()操作变化过来的,也就是pre[s]={'A'+0,tmp},tmp就代表我们上一个字符,s就代表经过‘A’+i操作后变换后的字符。这样,整个思路就完事了。
注意:在我们输出操作字符的时候,我们可以从终点往起点推,然后,再让整个字符串进行反转,这样就可以得到操作字符的正常最小字典序了。
上代码:
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
#include<deque>
#include <iomanip>
#include<sstream>
#include<numeric>
#include<map>
#include<limits.h>
#include<unordered_map>
#include<set>
#define int long long
#define MAX 110
#define inf 0x3f3f3f3f
#define _for(i,a,b) for(int i=a;i<(b);i++)
using namespace std;
typedef pair<int, int> PII;
int n, m,k;
int counts;
int dx[] = { 0,1,0,-1};
int dy[] = { 1,0,-1,0 };
int cunchu[2][4];
char bianhao[MAX];
string start, end1;
unordered_map<string, int>dist;
unordered_map<string, pair<char, string>>pre;
queue<string>q;
void sets(string a) {
for (int i = 0; i < 4; i++) {
cunchu[0][i] = a[i];
}
for (int i = 3, j = 4; i >= 0; i--, j++) {
cunchu[1][i] = a[j];
}
}
string get() {
string res;
for (int i = 0; i < 4; i++) {
res += cunchu[0][i];
}
for (int i = 3; i >= 0; i--)
res += cunchu[1][i];
return res;
}
string A(string a) {
sets(a);
for (int i = 0; i < 4; i++) {
swap(cunchu[0][i], cunchu[1][i]);
}
return get();
}
string B(string a) {
sets(a);
char tmp1 = cunchu[0][3];
char tmp2 = cunchu[1][3];
for (int i = 3; i >= 1; i--) {
for (int j = 0; j < 2; j++) {
cunchu[j][i] = cunchu[j][i - 1];
}
}
cunchu[0][0] = tmp1;
cunchu[1][0] = tmp2;
return get();
}
string C(string a) {
sets(a);
int tmp = cunchu[0][1];
cunchu[0][1] = cunchu[1][1];
cunchu[1][1] = cunchu[1][2];
cunchu[1][2] = cunchu[0][2];
cunchu[0][2] = tmp;
return get();
}
int bfs(string start,string end1) {
q.push(start);
dist[start] = 0;
while (!q.empty()) {
auto tmp = q.front();
q.pop();
if (tmp == end1)
return dist[end1];
string m[3];
m[0] = A(tmp);
m[1] = B(tmp);
m[2] = C(tmp);
for (int i = 0; i < 3; i++) {
string buf = m[i];
if (!dist.count(buf)) {
dist[buf] = dist[tmp] + 1;
pre[buf] = { i + 'A',tmp };
if (buf == end1)
return dist[end1];
q.push(buf);
}
}
}
return -1;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
for (int i = 1; i <= 8; i++) {
start += i + '0';
}
for (int i = 1; i <= 8; i++) {
int x;
cin >> x;
end1 += x + '0';
}
int res = bfs(start, end1);
cout << res << endl;
string cao;
while (end1 != start) {
cao += pre[end1].first;
end1 = pre[end1].second;
}
reverse(cao.begin(), cao.end());
if (cao.size())
cout << cao << endl;
return 0;
}