给九个格子1,2,...9 一共9个数组,每次只能交换9与他直接相邻的数字,计算从一种状态到另外一种状态的最少移动步数。
用广搜+康拓展开的方法实现。
#include "stdafx.h"
#include<iostream> #include<string> #include <vector> #include <math.h>#include <map>#include <queue>using namespace std;const int MAX=400000;long int fac[]={1,1,2,6,24,120,720,5040,40320,362880}; //表示阶乘运算的结果//long int fac[]={0!,1!,2!,3!,4!,5!,6!,7!,8!,9!};//康拓展开int Cantor(int *s,int n){ int i,j,num,temp; num=0; for(i=0;i<n;i++) { temp=0; //temp记录当前数位前面的低数位中小于当前位数上的数字的个数 for(j=i+1;j<n;j++) if(s[j]<s[i]) temp++; num+=fac[n-1-i]*temp; //乘以相应的阶乘 } return num;}//康拓展开逆运算void CantorReverse(int index,int *p,int n){ //index--; //勿丢 int i,j; bool hash[10]={0}; for(i=0;i<n;i++) { int tmp=index/fac[n-1-i]; //tmp表示有tmp个数字比当前位置上的数字小 for(j=0;j<=tmp;j++) if(hash[j]) tmp++; p[i]=tmp+1; hash[tmp]=1; index%=fac[n-1-i]; } return;}//交换int swapSquares(int index, int i, int j){ int s[10]; CantorReverse(index, s, 9); int temp=s[i]; s[i]=s[j]; s[j]=temp; index=Cantor(s, 9); return index;}struct STATE{ int value; int pos; int step;};int bfs(STATE start, STATE end){ bool visited[MAX];//记录bfs是否扫描过 //每个状态可以到达的位置 char *neighbour[]={"13","024","15","046","1357","248","37","468","57"}; queue<STATE> Q; Q.push(start); while(!Q.empty()) { STATE cur=Q.front(); Q.pop(); char *p=neighbour[cur.pos]; while(*p!='\0') { STATE tmp; tmp.value = swapSquares(cur.value, cur.pos, *p-'0'); tmp.pos=*p-'0'; tmp.step=cur.step+1; if(tmp.value == end.value) return tmp.step; if(visited[tmp.value] == false) { Q.push(tmp); visited[tmp.value]=true; } p++; } } return -1;}int main(int argc,char *argv){ int s1[10],s2[10]; STATE start, end; start.step=0; //输入开始状态 for (int i = 0; i< 9;i ++) { scanf("%d", &s1[i]); if(s1[i]==9) start.pos=i; } //输入结束状态 for (int i = 0; i< 9;i ++) scanf("%d", &s2[i]); start.value=Cantor(s1,9); end.value=Cantor(s2,9); if(start.value == end.value) printf("%d\n",0); else printf("%d\n", bfs(start, end)); return 0;}