您的位置:首页 > 其它

HDU 3459 Rubik 2×2×2 二阶魔方还原(IDA*)

2012-07-16 18:15 99 查看
转载请注明出处,谢谢 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: