这题需要用数组记录每个block的位置。启发函数:d+wa(8-当前最多相同个数)>maxd直接退出
AC代码:
#include<cstdio>
#include<cstring> //IDA* 每次旋转最多只能增加一个相同的 启发函数:d+wa<=maxd
#include<algorithm>
using namespace std;
int block[24];
int pos[8][7]={
{0,2,6,11,15,20,22},{1,3,8,12,17,21,23},
{10,9,8,7,6,5,4},{19,18,17,16,15,14,13},
{23,21,17,12,8,3,1},{22,20,15,11,6,2,0},
{13,14,15,16,17,18,19},{4,5,6,7,8,9,10}
};
int goal[8]={6,7,8,11,12,15,16,17};
int dis[100000]; //记录步骤
void turn(int dir){
int fir=block[pos[dir][0]];
for(int i=0;i<6;++i){
block[pos[dir][i]]=block[pos[dir][i+1]];
}
block[pos[dir][6]]=fir;
}
bool is_ok(){
for(int i=0;i<7;++i){
if(block[goal[i]]!=block[goal[i+1]]) return false;
}
return true;
}
bool dfs(int d,int maxd){
if(is_ok()){ //找到答案
if(!maxd) printf("No moves needed\n%d\n",block[6]);
else {
for(int i=0;i<maxd;++i)
printf("%c",dis[i]+'A');
printf("\n%d\n",block[6]);
}
return true;
}
//判断当前是否有可能在maxd下得到正确答案
int a=0,b=0,c=0;
for(int i=0;i<8;++i){
if(block[goal[i]]==1) ++a;
else if(block[goal[i]]==2) ++b;
else if(block[goal[i]]==3) ++c;
}
int wa=8-max(max(a,b),c);
if(d+wa>maxd) return false;
int old[24];
memcpy(old,block,sizeof(block));
for(int i=0;i<8;++i){
dis[d]=i;
turn(i);
if(dfs(d+1,maxd)) return true;
memcpy(block,old,sizeof(old));
}
return false;
}
int main() {
while(1){
for(int i=0;i<24;++i) {
scanf("%d",&block[i]);
if(!block[i]) return 0;
}
for(int maxd=0;;++maxd){
if(dfs(0,maxd)) break;
}
}
return 0;
}
如有不当之处欢迎指出!