我们可以把每一种棋盘状态看作一个结点,因为一共就8位数,所以结点数是有限的。也就是说我们可以用这些结点构建一个无向图。
又因为每次转换的“花费”是相同的,即花一次转换机会
因此图上的边权也相等
而题目的问题就可以转化为求边权相等的图上两个点的最短距离
那么就很明显是bfs了
#include
using namespace std;
#define fi first
#define se second
string st = "12345678", dt = "";
//和起点的距离
mapdis;
//手写队列
string q[N * N];
//记录路径 -> 从哪个状态来,以什么方式来的
map >pre;
//三种操作
string op(string now, char c){
string ans = "";
if(c == 'A'){
for(int i = 7; i >= 4; i--) ans += now[i];
for(int i = 3; i >= 0; i--) ans += now[i];
}
else if(c == 'B'){
ans += now[3];
for(int i = 0; i < 3; i++) ans += now[i];
for(int i = 5; i <= 7; i++) ans += now[i];
ans += now[4];
}
else{
int gs[] = {0, 6, 1, 3, 4, 2, 5, 7};
for(int i = 0; i < 8; i++) ans += now[gs[i]];
}
return ans;
}
//bfs模板
int bfs(){
int hh = 0, tt = -1;
q[++tt] = st;
dis[st] = 0;
while(hh <= tt){
auto tp = q[hh++];
if(tp == dt) return dis[dt];
string temp = op(tp, 'A');
if(!dis.count(temp)){
dis[temp] = dis[tp] + 1;
q[++tt] = temp;
pre[temp] = {tp, 'A'};
}
temp = op(tp, 'B');
if(!dis.count(temp)){
dis[temp] = dis[tp] + 1;
q[++tt] = temp;
pre[temp] = {tp, 'B'};
}
temp = op(tp, 'C');
if(!dis.count(temp)){
dis[temp] = dis[tp] + 1;
q[++tt] = temp;
pre[temp] = {tp, 'C'};
}
}
}
int main(){
for(int i = 0; i < 8; i++){
int x;
scanf("%d", &x);
dt += x + '0';
}
int t = bfs();
cout << t << endl;
string path = "", now = dt;
while(now != st){
path += pre[now].se;
now = pre[now].fi;
}
reverse(path.begin(), path.end());
if(t) cout << path << endl;
return 0;
}
如果觉得不错,不妨给个再走呗~