HDU上的八数码 数据强的一B
首先:双向广搜
先处理正向搜索,再处理反向搜索,直至中途相遇
visit 和 队列都是独立的。 可以用一个过程来完成这2个操作,减少代码量。(一般还要个深度数组)
优化效率很强
逆序数优化
在忽略空格的情况,会发现 空格无论怎么变,1-8的排列的逆序数始终要为偶数,才能有解(空格无视)
而且证明得出:如果满足逆序条件,必定有解!
拓展
N*N的情况
N×N的棋盘,N为奇数时,与八数码问题相同。
N为偶数时,空格每上下移动一次,奇偶性改变。称空格位置所在的行到目标空格所在的行步数为空格的距离(不计左右距离),若两个状态的可相互到达,则有,两个状态的逆序奇偶性相同且空格距离为偶数,或者,逆序奇偶性不同且空格距离为奇数数。否则不能。
>推广到三维N×N×N
其实,三维的结论和二维的结论是一样的。
考虑左右移动空格,逆序不变;同一层上下移动空格,跨过N-1个格子;上下层移动空格,跨过N^2-1个格子。
当N为奇数时,N-1和N^2-1均为偶数,也就是任意移动空格逆序奇偶性不变。那么逆序奇偶性相同的两个状态可相互到达。
当N为偶数时,N-1和N^2-1均为奇数,也就是令空格位置到目标状态空格位置的y z方向的距离之和,称为空格距离。若空格距离为偶数,两个逆序奇偶性相同的状态可相互到达;若空格距离为奇数,两个逆序奇偶性不同的状态可相互到达。
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <ctime> #include <algorithm> #include <iostream> #include <sstream> #include <string> #include <queue> #define oo 0x13131313 using namespace std; struct node { int operator[](int index) const { return A[index]; } int& operator[](int index) { return A[index]; } int A[10]; int xnum; int deep; int Contor; void JSContor() { int temp=0,p=1; for(int i=8;i>=0;i--) { int tot=0; for(int j=0;j<i;j++) if(A[j]<A[i]) tot++; temp+=(A[i]-tot-1)*p; p=p*(9-i); } Contor=temp+1; } }; int visit[2][370000]; int dist[2][370000]; int DEEP[2][370000]; int dANS[2][370000]; char f[4]={'u','d','l','r'}; queue <node> Q[2]; node start; node End; char AAA[20]; void init() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); } void input() { memset(visit,0,sizeof(visit)); for(int i=0;i<9;i++) { if(AAA[i]=='x') { start[i]=9; start.xnum=i; } else start[i]=AAA[i]-'0'; End[i]=i+1; } End.xnum=8; End.deep=0; start.deep=0; } void csh() { while(Q[0].empty()!=1) Q[0].pop(); start.JSContor(); visit[0][start.Contor]=1; Q[0].push(start); while(Q[1].empty()!=1) Q[1].pop(); End.JSContor(); visit[1][End.Contor]=1; Q[1].push(End); } int GAN(int pos) { node s,t; s=Q[pos].front(); Q[pos].pop(); if(visit[pos^1][s.Contor]==1) { return s.Contor; } s.deep++; // t=s; if(((t.xnum)/3)!=0) { swap(t[t.xnum],t[t.xnum-3]); t.xnum=t.xnum-3; t.JSContor(); if(visit[pos][t.Contor]==0) { Q[pos].push(t); visit[pos][t.Contor]=1; dist[pos][t.Contor]=s.Contor; dANS[pos][t.Contor]=0; DEEP[pos][t.Contor]=t.deep; } } // t=s; if(((t.xnum)/3)!=2) { swap(t[t.xnum],t[t.xnum+3]); t.xnum=t.xnum+3; t.JSContor(); if(visit[pos][t.Contor]==0) { Q[pos].push(t); visit[pos][t.Contor]=1; dist[pos][t.Contor]=s.Contor; dANS[pos][t.Contor]=1; DEEP[pos][t.Contor]=t.deep; } } // t=s; if(t.xnum%3!=0) { swap(t[t.xnum],t[t.xnum-1]); t.xnum--; t.JSContor(); if(visit[pos][t.Contor]==0) { Q[pos].push(t); visit[pos][t.Contor]=1; dist[pos][t.Contor]=s.Contor; dANS[pos][t.Contor]=2; DEEP[pos][t.Contor]=t.deep; } } // t=s; if((t.xnum+1)%3!=0) { swap(t[t.xnum],t[t.xnum+1]); t.xnum++; t.JSContor(); if(visit[pos][t.Contor]==0) { Q[pos].push(t); visit[pos][t.Contor]=1; dist[pos][t.Contor]=s.Contor; dANS[pos][t.Contor]=3; DEEP[pos][t.Contor]=t.deep; } } return 0; } void twobfs() { void print(int ok1); csh(); int ok1=0,ok2=0; while(Q[0].empty()!=1&&Q[1].empty()!=1) { ok1=GAN(0); if(ok1!=0) break; ok2=GAN(1); if(ok2!=0) {ok1=ok2;break;} } print(ok1); } char ANS[20]; void print(int ok1) { int tot=1; for(int p=ok1;p!=start.Contor;p=dist[0][p]) { ANS[tot]=f[dANS[0][p]]; tot++; } for(int i=tot-1;i>=1;i--) printf("%c",ANS[i]); tot=1; for(int p=ok1;p!=End.Contor;p=dist[1][p]) { ANS[tot]=f[dANS[1][p]^1]; tot++; } for(int i=1;i<tot;i++) printf("%c",ANS[i]); printf("\n"); } int OK=1; int JZyj() { int tot1=0; for(int i=0;i<=8;i++) for(int j=0;j<i;j++) { if(start[i]!=9&&start[j]!=9) if(start[i]<start[j]) tot1++; } if(tot1%2==0) return 1; else return 0; } int main() { //init(); char c; while(scanf("%c %c %c %c %c %c %c %c %c\n",&AAA[0],&AAA[1],&AAA[2],&AAA[3],&AAA[4],&AAA[5],&AAA[6],&AAA[7],&AAA[8])!=EOF) { input(); if( JZyj()) twobfs(); else printf("unsolvable\n"); } }
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <ctime> #include <algorithm> #include <iostream> #include <sstream> #include <string> #include <queue> #define oo 0x13131313 using namespace std; struct node { int operator[](int index) const { return A[index]; } int& operator[](int index) { return A[index]; } int A[10]; int xnum; int deep; int Contor; void JSContor() { int temp=0,p=1; for(int i=8;i>=0;i--) { int tot=0; for(int j=0;j<i;j++) if(A[j]<A[i]) tot++; temp+=(A[i]-tot-1)*p; p=p*(9-i); } Contor=temp+1; } }; int visit[2][370000]; int dist[2][370000]; int DEEP[2][370000]; int dANS[2][370000]; char f[4]={'u','d','l','r'}; int fx[5]={-1,+1,0,0}; int fy[5]={0,0,-1,+1}; queue <node> Q[2]; node start; node End; char AAA[20]; void init() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); } void input() { memset(visit,0,sizeof(visit)); for(int i=0;i<9;i++) { if(AAA[i]=='x') { start[i]=9; start.xnum=i; } else start[i]=AAA[i]-'0'; End[i]=i+1; } End.xnum=8; End.deep=0; start.deep=0; } void csh() { while(Q[0].empty()!=1) Q[0].pop(); start.JSContor(); visit[0][start.Contor]=1; Q[0].push(start); while(Q[1].empty()!=1) Q[1].pop(); End.JSContor(); visit[1][End.Contor]=1; Q[1].push(End); } int GAN(int pos) { node s,t; int x,y,p; s=Q[pos].front(); Q[pos].pop(); if(visit[pos^1][s.Contor]==1) { return s.Contor; } s.deep++; x=s.xnum/3;y=s.xnum%3; for(int i=0;i<=3;i++) { t=s; if(x+fx[i]<=2&&x+fx[i]>=0&&y+fy[i]<=2&&y+fy[i]>=0) { p=(x+fx[i])*3+y+fy[i]; swap(t[t.xnum],t[p]); t.xnum=p; t.JSContor(); if(visit[pos][t.Contor]==0) { Q[pos].push(t); visit[pos][t.Contor]=1; dist[pos][t.Contor]=s.Contor; dANS[pos][t.Contor]=i; DEEP[pos][t.Contor]=t.deep; } } } return 0; } void twobfs() { void print(int ok1); csh(); int ok1=0,ok2=0; while(Q[0].empty()!=1&&Q[1].empty()!=1) { ok1=GAN(0); if(ok1!=0) break; ok2=GAN(1); if(ok2!=0) {ok1=ok2;break;} } print(ok1); } char ANS[20]; void print(int ok1) { int tot=1; for(int p=ok1;p!=start.Contor;p=dist[0][p]) { ANS[tot]=f[dANS[0][p]]; tot++; } for(int i=tot-1;i>=1;i--) printf("%c",ANS[i]); tot=1; for(int p=ok1;p!=End.Contor;p=dist[1][p]) { ANS[tot]=f[dANS[1][p]^1]; tot++; } for(int i=1;i<tot;i++) printf("%c",ANS[i]); printf("\n"); } int OK=1; int JZyj() { int tot1=0; for(int i=0;i<=8;i++) for(int j=0;j<i;j++) { if(start[i]!=9&&start[j]!=9) if(start[i]<start[j]) tot1++; } if(tot1%2==0) return 1; else return 0; } int main() { //init(); char c; while(scanf("%c %c %c %c %c %c %c %c %c\n",&AAA[0],&AAA[1],&AAA[2],&AAA[3],&AAA[4],&AAA[5],&AAA[6],&AAA[7],&AAA[8])!=EOF) { input(); if( JZyj()) twobfs(); else printf("unsolvable\n"); } }