[置顶] HDU 1043 eight 八数码

 

其实最重要的就是判重这个关卡,说到底用的也是一个哈希的算法,利用当前这个数的逆序数来构建的。

//ashione 2011-3-31 #include<iostream> #include<queue> #include<string> using namespace std; #define N 10 #define MAX 362881 //最多可能有9!个排列 int fac[]={1,1,2,6,24,120,720,5040,40320,362880};//康托展开数列 bool visited[MAX]; string route[MAX]; int move[4][2]={{-1,0},{1,0},{0,-1},{0,1}}; // 上 下 左 右 ,因为是逆序查找 所以对应下面为 下 上 右 左,如change数组 char change[5]="durl"; int cantor(int s[])//康托判重 { int sum=0; for(int i=0;i<9;i++) { int num=0; for(int j=i+1;j<9;j++) s[j]<s[i]?num++:1; sum=sum+(num*fac[8-i]); } return sum+1; } typedef struct eight{ int p[N]; int now,position;//now 为当前‘x’所在的位置(0-8),position为在排列中的序列号 string route; //从终点到起点的路程 }link; void bfs() { int i; queue<link> q; link first,second; for(i=0;i<8;i++) //设终点为 123456780 first.p[i]=i+1; first.p[i]=0,first.now=8,first.position=cantor(first.p); first.route=""; route[first.position]=""; q.push(first); visited[first.position]=true; while(!q.empty()) { first=q.front(); q.pop(); for(i=0;i<4;i++) { int x=first.now/3+move[i][0]; int y=first.now%3+move[i][1]; if(x<0 || x>2 || y <0 || y>2) continue; second=first,second.now=x*3+y; second.p[first.now]=second.p[second.now]; second.p[second.now]=0; second.position=cantor(second.p); if(!visited[second.position])//判断是否到过 { second.route+=change[i]; visited[second.position]=true; route[second.position]=second.route; q.push(second); } } } } void ouput(int k) { if(!visited[k]) { cout<<"unsolvable"<<endl; return ; } for(int i=route[k].size()-1;i>=0;i--)//逆序输出 cout<<route[k][i]; cout<<endl; } int main() { bfs(); int p[N]; char c; while(cin>>c) { int i=0; c=='x'?p[i]=0:p[i]=c-'0'; for(i=1;i<9;i++) cin>>c,c=='x'?p[i]=0:p[i]=c-'0'; int k=cantor(p); ouput(k); } }

你可能感兴趣的:(c,算法,String,struct)