站长软件下载 东莞佳利热转印机 空白卫衣批发 个性服饰定制

八数码问题和bfs中的判重方法

所谓八数码问题就是有一个编号为1~8的正方形滑块被摆成3行3列(留一个格子空着)每次可以把与空格相邻的滑块(有公共边的才算相邻)移动到空格中,而它原来的位置就成为了新的空格,给定初始的局面和目标局面,你的任务就是计算出最少的移动步数,如果无法达到目标局面,就输出-1.

AC代码:

  1. #include<cstdio>  
  2. #include<string.h>  
  3. #include<stdlib.h>  
  4. #include<string>  
  5. #include<algorithm>  
  6. #define N 1000000  
  7. #define M 1000003  
  8. using namespace std;  
  9. typedef int State[9];  
  10. State st[N],goal;  
  11. int dist[N];  
  12. int dx[]={-1,1,0,0};  
  13. int dy[]={0,0,-1,1};  
  14. int head[N],nex[N];  
  15. int Hash(State& s)  
  16. {  
  17.     int v=0;  
  18.     for(int i=0;i<9;++i) v=v*10+s[i];  
  19.     return v%M;  
  20. }  
  21. int _insert(int s)  
  22. {  
  23.     int h=Hash(st[s]);  
  24.     int u=head[h];  
  25.     while(u)//判断该状态是否已经存在  
  26.     {  
  27.         if(memcmp(st[u],st[s],sizeof(st[s]))==0) return 0;  
  28.          u=nex[u];  
  29.     }  
  30.     nex[s]=head[h];//插入到链表中  
  31.     head[h]=s;  
  32.     return 1;  
  33. }  
  34. int bfs()  
  35. {  
  36.     memset(head,0,sizeof(head));  
  37.     memset(dist,0,sizeof(dist));  
  38.     int front=1,rear=2;  
  39.     while(front<rear)  
  40.     {  
  41.         State& s=st[front];//用引用简化代码  
  42.         if(memcmp(goal,s,sizeof(s))==0) return front;//找到目标状态,返回  
  43.         int z;  
  44.         for(z=0;z<9&&s[z];z++);//找到0的位置  
  45.         int x=z/3;  
  46.         int y=z%3;//获取0的行列编号  
  47.         for(int i=0;i!=4;++i)  
  48.         {  
  49.             int newx=x+dx[i];  
  50.             int newy=y+dy[i];  
  51.             int newz=newx*3+newy;  
  52.             if(newx>=0&&newx<3&&newy>=0&&newy<3)  
  53.             {  
  54.                 State& t=st[rear];  
  55.                 memcpy(&t,&s,sizeof(s));//扩展新节点  
  56.                 t[newz]=s[z];  
  57.                 t[z]=s[newz];  
  58.                 dist[rear]=dist[front]+1;//更新新节点的距离  
  59.                 if(_insert(rear)) rear++;//如果成功插入,则修改队尾指针  
  60.             }  
  61.         }  
  62.         front++;//扩展完毕修改队首指针  
  63.     }return -1;  
  64. }  
  65. int main()  
  66. {  
  67.     int T;  
  68.     scanf("%d",&T);  
  69.     while(T--)  
  70.     {  
  71.         for(int i=0;i!=9;++i) scanf("%d",&st[1][i]);  
  72.         for(int i=0;i!=9;++i) scanf("%d",&goal[i]);  
  73.         int ans=bfs();  
  74.         printf("%d\n",(ans==-1)?-1:dist[ans]);  
  75.     }return 0;  
  76.   
  77. }  
  78. /* 
  79. 2 6 4 1 3 7 0 5 8 
  80. 8 1 5 7 3 6 4 0 2 
  81. 31 
  82. */  
posted on 2012-10-19 09:38  pc蛋蛋  阅读(496)  评论(0编辑  收藏  举报