这题的难点在于移动的表示和如何标记已经访问过的图;
参考了大牛的代码:
https://www.cnblogs.com/tt123/p/3411377.html
ida做法有个好处,不需要去标记图,只要不往回走就行,ida会卡住有限步数,
在最优的步数情况下,同一个图并不会重复访问。
这是ida相对bfs的一个很大的有点。
代码如下:
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int Ms[8][7] ={
0, 2, 6,11,15,20,22, //A
1, 3, 8,12,17,21,23, //B
10, 9, 8, 7, 6, 5, 4, //C
19,18,17,16,15,14,13, //D
23,21,17,12, 8, 3, 1, //E
22,20,15,11, 6, 2, 0, //F
13,14,15,16,17,18,19, //G
4, 5, 6, 7, 8, 9,10, //H
};
int R[8] = {5,4,7,6,1,0,3,2}; //返回
int Mid[8] = {6,7,8,11,12,15,16,17},mp[30];
int ans[100];
int get(void){
int t[3]={0};
for(int i=0;i<8;++i){
++t[mp[Mid[i]]-1];
}
return max(t[0],max(t[1],t[2]));
}
void Move(int x){
int tmp=mp[Ms[x][0]];
for(int i=0;i<6;++i){
mp[Ms[x][i]]=mp[Ms[x][i+1]];
}
mp[Ms[x][6]]=tmp;
return;
}
bool ida(int x,int depth){
if(x>depth)
return false;
for(int i=0;i<8;++i){
if(R[i]==ans[x-1]) //防止往回走
continue;
Move(i);
ans[x]=i;
int t=get();
t=8-t;
if(t==0)
return true;
if(x+t<=depth&&ida(x+1,depth))
return true;
Move(R[i]);
}
return false;
}
int main(){
ans[0]=10;
while(scanf("%d",&mp[0])&&mp[0]){
for(int i=1;i<24;++i)
scanf("%d",&mp[i]);
int depth=get();
if(depth==8){
puts("No moves needed");
printf("%d\n",mp[7]);
continue;
}
for(depth=8-depth;1;++depth){
if(ida(1,depth)){
for(int i=1;i<=depth;++i){
printf("%c",ans[i]+'A');
}
printf("\n%d\n",mp[7]);
break;
}
}
}
return 0;
}