POJ 1077 八数码难题

终于自己AC了这道八数码难题,用的方法是最最普通的单项BFS+Hash,这里主要的难点在于如何保存状态,其实,在八数码里所有的状态共有9!种=362880种,所以在每个转台节点,我需要一个char state[3][3]来记录当前棋盘的状态,用一个int x,y来记录当前x的位置,用char operation来记录从父状态到这个状态需要进行的操作,当然,为了记录路径,我需要记录它的父节点,然而这个父节点要怎么去记录呢,刚开始的时候对于这个问题纠结了很久,曾经直接把结构体存在队列里面,然后用指针去引用它的父节点,殊不知,当出队操作后,声明的节点就是去了意义,所以这种做法是错误的。看了别人的思路,把所有的状态节点都存在一个结构体数组里面,并且用一个count记录当钱数组里面状态的个数,因为每出来一个新状态,就把它赋值给相应的数组元素。所以,一个状态的父状态就可以指向父状态的数组下表index,到时候可以直接读取。还有一点需要注意的是进行hash时,不同的MAX取值可能会导致不同的结果,一般讲MAX取较大的素数,事实证明,用stl  <set>来存状态去重效率会低很多,用hash的话效率会高一些。对于路径的寻找,既然知道了每一状态的操作,则可以从目标状态开始将操作压栈,到时候出栈即为正确的从初始态到目标态的操作。

下面代码,进攻参考,欢迎批评指正

 

View Code
  1 #include<stdio.h>
2 #include<iostream>
3 #include<string.h>
4 #include<stdlib.h>
5 #include<queue>
6 #include<set>
7 #include<stack>
8 using namespace std;
9
10 #define MAX 8000003
11
12 struct node
13 {
14 char state[3][3];
15 int parent;
16 int x,y;
17 char operation;
18 }allstate[400000];
19 int hash[MAX];
20 //set<int> stateSet;
21 queue<int> qu;
22 stack<char>path;
23 int dirx[4]={1,-1,0,0};
24 int diry[4]={0,0,1,-1};
25
26
27 int getHash(node n)
28 {
29 int i,j,sum=0;
30 for(i=0;i<3;i++)
31 for(j=0;j<3;j++)
32 sum=sum*10+n.state[i][j]-'0';
33 return sum%MAX;
34 }
35
36 void getPath(node target)
37 {
38 node temp=target;
39 while(temp.parent!=-1)
40 {
41 path.push(temp.operation);
42 temp=allstate[temp.parent];
43 }
44 }
45
46 void BFS(node head)
47 {
48 memset(hash,0,sizeof(hash));
49 int stateCount=0,i,hashValue;
50 node outNode,newNode;
51 bool isOk=false;
52
53 hash[getHash(head)]=1;
54 allstate[stateCount]=head;
55 qu.push(stateCount);
56 stateCount++;
57
58 while(!qu.empty())
59 {
60 int index=qu.front();
61 qu.pop();
62 outNode=allstate[index];
63
64 if(getHash(outNode)==3456735)
65 {
66 isOk=true;
67 break;
68 }
69
70 int x=allstate[index].x;
71 int y=allstate[index].y;
72
73 for(i=0;i<4;i++)
74 {
75 int newx=x+dirx[i];
76 int newy=y+diry[i];
77 if(newx<0 || newx>2 || newy<0 || newy>2)continue;
78
79 newNode=outNode;
80
81 swap(newNode.state[x][y],newNode.state[newx][newy]);
82
83 hashValue=getHash(newNode);
84 if(hash[hashValue])continue;
85 //stateSet.insert(hashValue);
86 hash[hashValue]=1;
87
88 newNode.x=newx;
89 newNode.y=newy;
90 newNode.parent=index;
91
92 if(dirx[i]==0)
93 {
94 if(diry[i]==1)newNode.operation='r';
95 else newNode.operation='l';
96 }
97 if(diry[i]==0)
98 {
99 if(dirx[i]==1)newNode.operation='d';
100 else newNode.operation='u';
101 }
102 qu.push(stateCount);
103 allstate[stateCount++]=newNode;
104
105 }
106 }
107 if(!isOk)
108 {
109 puts("unsolvable");return;
110 }
111 getPath(outNode);
112 while(!path.empty())
113 {
114 cout<<path.top();
115 path.pop();
116 }
117 cout<<endl;
118
119 }
120
121 int main(void)
122 {
123 int i,j;
124 node head;
125 for(i=0;i<3;i++)
126 {
127 for(j=0;j<3;j++)
128 {
129 cin>>head.state[i][j];
130 if(head.state[i][j]=='x')
131 {
132 head.state[i][j]='0';
133 head.x=i;
134 head.y=j;
135 }
136 }
137 }
138 head.parent=-1;
139 head.operation='0';
140 BFS(head);
141 return 0;
142 }


posted on 2012-01-06 22:33  lonelycatcher  阅读(490)  评论(0编辑  收藏  举报

导航