转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
二阶魔方还原,已经好复杂,好抽象了。
题目不要求最短的,不过IDA*写出的应该是最短的吧,而且是字典序最小的。
先说一下这个二阶魔方的一个特点,虽然有3种旋转,但是总有一块是不动的,就是后面靠左靠下的那个,既然不动,魔方其中3个面的颜色就确定了,通过这三个面的颜色就可以确定其它3个面的颜色。
这样就可以得到一个估价函数H,不过实在是太弱的剪枝了。6个面的颜色都有,就可以根据这个找到有几个位置上的和目标不同,每次旋转可以改变8个位置,也就是(总数+7)/8;
代码写得很坑爹,不过我估计这也没办法,看别人代码也挺长的,不过效率差别好大,继续想剪枝。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<string>
#include<vector>
#include<algorithm>
#include<map>
#include<set>
#define inf 1<<30
using namespace std;
struct Node{
int x,y;
}block[8][3],side[6][4];//记录魔方的八个立方体的三个面,每个面的4个坐标
char str[10][10];
char each_col[6]; //每个面的颜色,分别为上,左,前,右,后,下
bool flag;
int ans[100];
int depth;
void Init(){ //获得每个立方体的每个面坐标,以及魔方每个面各个点的坐标
block[0][0].x=3;block[0][0].y=2;block[0][1].x=3;block[0][1].y=1;block[0][2].x=4;block[0][2].y=2;
block[1][0].x=3;block[1][0].y=3;block[1][1].x=3;block[1][1].y=4;block[1][2].x=4;block[1][2].y=3;
block[2][0].x=2;block[2][0].y=2;block[2][1].x=2;block[2][1].y=1;block[2][2].x=1;block[2][2].y=2;
block[3][0].x=2;block[3][0].y=3;block[3][1].x=1;block[3][1].y=3;block[3][2].x=2;block[3][2].y=4;
block[4][0].x=3;block[4][0].y=0;block[4][1].x=5;block[4][1].y=2;block[4][2].x=3;block[4][2].y=7;
block[5][0].x=5;block[5][0].y=3;block[5][1].x=3;block[5][1].y=5;block[5][2].x=3;block[5][2].y=6;
block[6][0].x=0;block[6][0].y=2;block[6][1].x=2;block[6][1].y=7;block[6][2].x=2;block[6][2].y=0;
block[7][0].x=0;block[7][0].y=3;block[7][1].x=2;block[7][1].y=5;block[7][2].x=2;block[7][2].y=6;
side[0][0].x=0;side[0][0].y=2;side[0][1].x=0;side[0][1].y=3;side[0][2].x=1;side[0][2].y=2;side[0][3].x=1;side[0][3].y=3;
side[1][0].x=2;side[1][0].y=0;side[1][1].x=2;side[1][1].y=1;side[1][2].x=3;side[1][2].y=0;side[1][3].x=3;side[1][3].y=1;
side[2][0].x=2;side[2][0].y=2;side[2][1].x=2;side[2][1].y=3;side[2][2].x=3;side[2][2].y=2;side[2][3].x=3;side[2][3].y=3;
side[3][0].x=2;side[3][0].y=4;side[3][1].x=2;side[3][1].y=5;side[3][2].x=3;side[3][2].y=4;side[3][3].x=3;side[3][3].y=5;
side[4][0].x=2;side[4][0].y=6;side[4][1].x=2;side[4][1].y=7;side[4][2].x=3;side[4][2].y=6;side[4][3].x=3;side[4][3].y=7;
side[5][0].x=4;side[5][0].y=2;side[5][1].x=4;side[5][1].y=3;side[5][2].x=5;side[5][2].y=2;side[5][3].x=5;side[5][3].y=3;
}
char get_color(int A,int B,int C){ //获得每个面的颜色,通过其中的3个面
for(int i=0;i<8;i++){
if(str[block[i][0].x][block[i][0].y]==each_col[A]&&str[block[i][1].x][block[i][1].y]==each_col[B]&&str[block[i][2].x][block[i][2].y]!=each_col[C])
return str[block[i][2].x][block[i][2].y];
if(str[block[i][1].x][block[i][1].y]==each_col[A]&&str[block[i][0].x][block[i][0].y]==each_col[B]&&str[block[i][2].x][block[i][2].y]!=each_col[C])
return str[block[i][2].x][block[i][2].y];
if(str[block[i][0].x][block[i][0].y]==each_col[A]&&str[block[i][2].x][block[i][2].y]==each_col[B]&&str[block[i][1].x][block[i][1].y]!=each_col[C])
return str[block[i][1].x][block[i][1].y];
if(str[block[i][2].x][block[i][2].y]==each_col[A]&&str[block[i][0].x][block[i][0].y]==each_col[B]&&str[block[i][1].x][block[i][1].y]!=each_col[C])
return str[block[i][1].x][block[i][1].y];
if(str[block[i][1].x][block[i][1].y]==each_col[A]&&str[block[i][2].x][block[i][2].y]==each_col[B]&&str[block[i][0].x][block[i][0].y]!=each_col[C])
return str[block[i][0].x][block[i][0].y];
if(str[block[i][2].x][block[i][2].y]==each_col[A]&&str[block[i][1].x][block[i][1].y]==each_col[B]&&str[block[i][0].x][block[i][0].y]!=each_col[C])
return str[block[i][0].x][block[i][0].y];
}
}
void change_x(char maze[10][10]){ //x轴旋转
char tmp;
tmp=maze[2][4];maze[2][4]=maze[2][5];maze[2][5]=maze[3][5];maze[3][5]=maze[3][4];maze[3][4]=tmp;
tmp=maze[1][3];maze[1][3]=maze[2][6];maze[2][6]=maze[5][3];maze[5][3]=maze[3][3];maze[3][3]=tmp;
tmp=maze[0][3];maze[0][3]=maze[3][6];maze[3][6]=maze[4][3];maze[4][3]=maze[2][3];maze[2][3]=tmp;
}
void change_y(char maze[10][10]){ //y轴旋转
char tmp;
tmp=maze[2][0]; maze[2][0]=maze[2][6];maze[2][6]=maze[2][4]; maze[2][4]=maze[2][2]; maze[2][2]=tmp;
tmp=maze[2][1]; maze[2][1]=maze[2][7];maze[2][7]=maze[2][5]; maze[2][5]=maze[2][3]; maze[2][3]=tmp;
tmp=maze[0][2]; maze[0][2]=maze[0][3];maze[0][3]=maze[1][3]; maze[1][3]=maze[1][2]; maze[1][2]=tmp;
}
void change_z(char maze[10][10]){ //z轴旋转
char tmp;
tmp=maze[2][1]; maze[2][1]=maze[1][3];maze[1][3]=maze[3][4]; maze[3][4]=maze[4][2]; maze[4][2]=tmp;
tmp=maze[3][1]; maze[3][1]=maze[1][2];maze[1][2]=maze[2][4]; maze[2][4]=maze[4][3]; maze[4][3]=tmp;
tmp=maze[2][2]; maze[2][2]=maze[2][3];maze[2][3]=maze[3][3]; maze[3][3]=maze[3][2]; maze[3][2]=tmp;
}
int get_h(char maze[10][10]){
int ret=0;
for(int i=0;i<6;i++){
for(int j=0;j<4;j++)
if(maze[side[i][j].x][side[i][j].y]!=each_col[i])
ret++;
}
return (ret+7)/8;
};
void IDAstar(char maze[10][10],int tmp_depth){
if(flag)
return;
if(get_h(maze)>tmp_depth)
return;
if(tmp_depth==0){
flag=true;
return;
}
for(int i=0;i<3;i++){
if(flag)
return;
char temp[10][10];
for(int i=0;i<6;i++)
for(int j=0;j<8;j++)
temp[i][j]=maze[i][j];
if(i==0)
change_x(temp);
else if(i==1)
change_y(temp);
else
change_z(temp);
ans[tmp_depth]=i;
IDAstar(temp,tmp_depth-1);
}
}
int main(){
Init();
while(scanf("%s",str[0])!=EOF){
for(int i=1;i<6;i++)
scanf("%s",str[i]);
if(strcmp(str[2],"........")==0)
break;
each_col[1]=str[3][0];each_col[5]=str[5][2];each_col[4]=str[3][7];//其中有一个方块一直没有动,可以确定最终结果的3个面的颜色
each_col[0]=get_color(1,4,5);
each_col[2]=get_color(1,5,4);
each_col[3]=get_color(4,5,1);
flag=false;
for(depth=get_h(str);;depth++){
IDAstar(str,depth);
if(flag){
for(int i=depth;i>0;i--)
printf("%c",ans[i]+'X');
printf("\n");
break;
}
}
}
return 0;
}