借鉴网址:http://blog.csdn.net/binwin20/article/details/9073941
思路:魔方的旋转方法总共有12种,
只考虑前面的四个正方形,上面向左旋转,跟下面向右旋转是一个效果,方法数可以除2..
向右旋转一次等于向左旋转两次,可以一起处理,方法数再减半.三种情况.代码很短.
只有两种颜色,很多重复状态.用map当hash页不会超时.100ms水过.比标程代码短时间少..
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> #include <stack> #include <map> #include <string> #define LL long long #define DB double #define SF scanf #define PF printf #define N 1<<24 #define bug cout<<"bug"<<endl; using namespace std; map<int,int> mp; struct nod{ int a[25]; int dis; }; int cc[20][15]={ {0,1,4,5,20,21,12,13}, {8,11,10,9}, {18,16,2,0,9,10,21,23}, {13,12,14,15}, {4,6,17,16,15,13,9,8}, {0,1,3,2}, }; void turn(nod &t,int c) { c<<=1; int tmp = t.a[cc[c][7]]; for(int i=7;i>0;i--) { t.a[cc[c][i]]=t.a[cc[c][i-1]]; } t.a[cc[c][0]] = tmp; tmp = t.a[cc[c][7]]; for(int i=7;i>0;i--) { t.a[cc[c][i]]=t.a[cc[c][i-1]]; } t.a[cc[c][0]] = tmp; tmp = t.a[cc[c|1][3]]; for(int i=3;i>0;i--) { t.a[cc[c|1][i]]=t.a[cc[c|1][i-1]]; } t.a[cc[c|1][0]] = tmp; } nod in; queue<nod> que; int gethas(nod &t) { int ret = 0; for(int i=0;i<24;i++) { ret = t.a[i]+(ret<<1); }return ret; } bool ok(nod &t) { for(int i=0;i<24;i+=4) { for(int j=1;j<4;j++) if(t.a[i]!=t.a[i+j]) return false; }return true; } int solve() { int con = 0; for(int i=0;i<24;i++) if(in.a[i]) con++; if(con%4) return -1; in.dis = 0; while(!que.empty()) que.pop(); que.push(in); mp.clear(); mp[gethas(in)] = 1; nod e,t; if(ok(in)) return t.dis; while(!que.empty()) { e = que.front();que.pop(); for(int i=0;i<3;i++) { t = e;t.dis++; turn(t,i); if(mp.find(gethas(t))==mp.end()) { mp[gethas(t)] = 1;//bug if(ok(t)) return t.dis; que.push(t); } turn(t,i); turn(t,i); if(mp.find(gethas(t))==mp.end()) { mp[gethas(t)] = 1;//bug if(ok(t)) return t.dis; que.push(t); } } }return -1; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif int cas;SF("%d",&cas); while(cas--) { for(int i=0;i<24;i++) SF("%d",&in.a[i]); int k = solve(); if(k==-1) printf("IMPOSSIBLE!\n"); else printf("%d\n",k); } return 0; }
官方标程
/** 23 10 23 10 010101 323232 01 32 6 3 412 5 */ #include <iostream> #include <cstring> #include <cstdio> #include <cstdlib> using namespace std; char md[6][4]; #define MAX 20000000 bool flag[16][16][16][16][16][16]; struct M { short int num[6]; short int lv; void print() { int i; for(i = 0; i < 6; i++) printf("%d ",num[i]); printf("\n"); return; } }queue[MAX]; M (*funp[6])(M m); bool check(M m) { int i; for(i = 0; i < 6; i++) { if(m.num[i] != 15 && m.num[i] != 0) return false; } return true; } M turnY_L(M tm) { M m; m.num[0] = (tm.num[0] >> 1) | ((tm.num[0] & 1) << 3); m.num[1] = (tm.num[1] & 6) | ((tm.num[4] & 1) << 3) | ((tm.num[4] & 2) >> 1); m.num[2] = (tm.num[2] & 12) | ((tm.num[1] & 1) << 1) | ((tm.num[1] & 8) >> 3); m.num[3] = (tm.num[3] & 9) | ((tm.num[2] & 2) << 1) | ((tm.num[2] & 1) << 1); m.num[4] = (tm.num[4] & 12) | ((tm.num[3] & 4) >> 1) | ((tm.num[3] & 2) >> 1); m.num[5] = tm.num[5]; return m; } M turnY_R(M tm) { M m; m.num[0] = ((tm.num[0] & 7) << 1) | ((tm.num[0] & 8) >> 3); m.num[1] = (tm.num[1] & 6) | ((tm.num[2] & 2) >> 1) | ((tm.num[2] & 1) << 3); m.num[2] = (tm.num[2] & 12) | ((tm.num[3] & 4) >> 1) | ((tm.num[3] & 2) >> 1); m.num[3] = (tm.num[3] & 9) | ((tm.num[4] & 1) << 1) | ((tm.num[4] & 2) << 1); m.num[4] = (tm.num[4] & 12) | ((tm.num[1] & 1) << 1) | ((tm.num[1] & 8) >> 3); m.num[5] = tm.num[5]; return m; } /*------------------------------------------------------------------------------------*/ M turnX_L(M tm) { M m; m.num[1] = (tm.num[1] >> 1) | ((tm.num[1] & 1) << 3); m.num[0] = (tm.num[0] & 9) | ((tm.num[2] & 1) << 2) | ((tm.num[2] & 8) >> 2); m.num[2] = (tm.num[2] & 6) | ((tm.num[5] & 9)); m.num[3] = tm.num[3]; m.num[4] = (tm.num[4] & 9) | ((tm.num[0] & 6)); m.num[5] = (tm.num[5] & 6) | ((tm.num[4] & 4) >> 2) | ((tm.num[4] & 2) << 2); return m; } M turnX_R(M tm) { M m; m.num[1] = ((tm.num[1] & 7) << 1) | ((tm.num[1] & 8) >> 3); m.num[0] = (tm.num[0] & 9) | ((tm.num[4] & 6)); m.num[2] = (tm.num[2] & 6) | ((tm.num[0] & 4) >> 2) | ((tm.num[0] & 2) << 2); m.num[3] = tm.num[3]; m.num[4] = (tm.num[4] & 9) | ((tm.num[5] & 8) >> 2) | ((tm.num[5] & 1) << 2); m.num[5] = (tm.num[5] & 6) | ((tm.num[2] & 9)); return m; } M turnZ_L(M tm) { M m; m.num[4] = (tm.num[4] >> 1) | ((tm.num[4] & 1) << 3); m.num[0] = (tm.num[0] & 3) | (tm.num[1] & 12); m.num[1] = (tm.num[1] & 3) | (tm.num[5] & 12); m.num[2] = tm.num[2]; m.num[3] = (tm.num[3] & 3) | (tm.num[0] & 12); m.num[5] = (tm.num[5] & 3) | (tm.num[3] & 12); return m; } M turnZ_R(M tm) { M m; m.num[4] = ((tm.num[4] & 7)<< 1) | ((tm.num[4] & 8) >> 3); m.num[0] = (tm.num[0] & 3) | (tm.num[3] & 12); m.num[1] = (tm.num[1] & 3) | (tm.num[0] & 12); m.num[2] = tm.num[2]; m.num[3] = (tm.num[3] & 3) | (tm.num[5] & 12); m.num[5] = (tm.num[5] & 3) | (tm.num[1] & 12); return m; } void record_flag(int num1,int num2,int num3,int num4,int num5,int num6) { //printf("%d %d %d %d %d %d\n",num1,num2,num3,num4,num5,num6); flag[num1][num2][num3][num4][num5][num6] = 1; flag[num4][num1][(num3>>1)|((num3&1)<<3)][num6][((num5&7)<<1)+((num3&8)>>3)][num2] = 1; flag[num6][num4][((num3&3)<<2)+((num3&12)>>2)][num2][((num5&3)<<2)+((num5&12)>>2)][num1] = 1; flag[num2][num6][((num3&7)<<1)|((num3&8)>>3)][num1][(num5>>1)+((num5&1)<<3)][num4] = 1; return; } int Search(M m) { funp[0] = turnX_L; funp[1] = turnX_R; funp[2] = turnY_L; funp[3] = turnY_R; funp[4] = turnZ_L; funp[5] = turnZ_R; M tmp,tm; int front,rear,i; front = rear = 0; memset(flag,0,sizeof(flag)); m.lv = 0; queue[rear++] = m; record_flag(m.num[0],m.num[1],m.num[2],m.num[3],m.num[4],m.num[5]); while(front < rear) { tmp = queue[front++]; if(check(tmp)) return tmp.lv; for(i = 0; i < 6; i++) { tm = funp[i](tmp); tm.lv = tmp.lv + 1; if(flag[tm.num[0]][tm.num[1]][tm.num[2]][tm.num[3]][tm.num[4]][tm.num[5]] == 0) { queue[rear++] = tm; record_flag(tm.num[0],tm.num[1],tm.num[2],tm.num[3],tm.num[4],tm.num[5]); } } } return -1; } int main() { int T,i,n1,n2,n3,n4,ans; freopen("data.in","r",stdin); freopen("data.out","w",stdout); scanf("%d",&T); M m; while(T--) { for(i = 0; i < 6; i++) { scanf("%d%d%d%d",&n1,&n2,&n3,&n4); m.num[i] = n1 + (n2 << 1) + (n3 << 3) + (n4 << 2); // printf("%d\n",m.num[i]); } ans = Search(m); if(ans != -1) printf("%d\n", ans); else printf("IMPOSSIBLE!\n"); } return 0; } 官方数据生成代码 #include <iostream> #include <cstring> #include <cstdio> #include <ctime> #include <cstdlib> using namespace std; int a[24] = {0,0,1,1,1,1,0,0,0,1,0,1,1,0,1,0,1,1,0,1,0,1,0,0}; int main() { int t1,t2,i; freopen("data.in","w",stdout); int T = 10; printf("%d\n",T); srand(0); while(T--) { t1 = rand()$; do { t2 = ((rand()$)*(rand()$))$; }while(a[t1]==a[t2]); a[t1] = a[t1] ^ a[t2]; a[t2] = a[t1] ^ a[t2]; a[t1] = a[t1] ^ a[t2]; for(i = 0; i < 24; i++) { printf("%d",a[i]); if(i % 4 == 3) printf("\n"); else printf(" "); } printf("\n"); } return 0; }
