代码一:以数组充当队列,利用结构体中的pre追溯上一个状态在数组(队列)中的下标:

POJ1077  Eight —— 正向BFS_i++POJ1077  Eight —— 正向BFS_i++_02
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <vector>
  7 #include <queue>
  8 #include <stack>
  9 #include <map>
 10 #include <string>
 11 #include <set>
 12 #define ms(a,b) memset((a),(b),sizeof((a)))
 13 using namespace std;
 14 typedef long long LL;
 15 const int INF = 2e9;
 16 const LL LNF = 9e18;
 17 const int MOD = 1e9+7;
 18 const int MAXN = 1e6+10;
 19 #define AIM  1     //123456789的哈希值为1
 20 
 21 struct node
 22 {
 23     int status;
 24     int s[9];
 25     int loc;
 26     char path;
 27     int pre;  //pre为上一个操作在队列中的下标,用于输出路径
 28 };
 29 
 30 int vis[MAXN], fac[9] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320};
 31 int dir[4][2] = { -1,0, 1,0, 0,-1, 0,1 };
 32 char op[4] = {'u', 'd', 'l', 'r'  };
 33 
 34 int cantor(int s[])  //获得哈希函数值
 35 {
 36     int sum = 0;
 37     for(int i = 0; i<9; i++)
 38     {
 39         int num = 0;
 40         for(int j = i+1; j<9; j++)
 41             if(s[j]<s[i])
 42                 num++;
 43         sum += num*fac[8-i];
 44     }
 45     return sum+1;
 46 }
 47 
 48 node que[MAXN];
 49 int front, rear;
 50 int bfs(node now)
 51 {
 52     ms(vis,0);
 53     front = rear = 0;
 54 
 55     now.status = cantor(now.s);
 56     vis[now.status] = 1;
 57     que[rear++] = now;
 58 
 59     node tmp;
 60     while(front!=rear)
 61     {
 62         now = que[front++];
 63         if(now.status==AIM)
 64             return front-1;
 65 
 66         int x = now.loc/3;
 67         int y = now.loc%3;
 68         for(int i = 0; i<4; i++)
 69         {
 70             int xx = x + dir[i][0];
 71             int yy = y + dir[i][1];
 72             if(xx>=0 && xx<=2 && yy>=0 && yy<=2)
 73             {
 74                 tmp = now;
 75                 tmp.s[x*3+y] = tmp.s[xx*3+yy];  //交换位置,下同
 76                 tmp.s[xx*3+yy] = 9;
 77                 tmp.status = cantor(tmp.s);
 78                 if(!vis[tmp.status])
 79                 {
 80                     vis[tmp.status] = 1;
 81                     tmp.loc = xx*3+yy;
 82                     tmp.path = op[i];     //保存操作
 83                     tmp.pre = front-1;  //保存当前结点的状态的上一个状态所在的结点在数组(队列)的下标
 84                     que[rear++] = tmp;
 85                 }
 86             }
 87         }
 88     }
 89     return -1;
 90 }
 91 
 92 void Print(int i)   //利用递归的特点(压栈),输出路径
 93 {
 94     if(i==0) return;    //到了目的状态,则退出。目的状态的结点在数组(队列)中的下标为0
 95     Print(que[i].pre);  //访问上一步
 96     putchar(que[i].path); //输出操作
 97 }
 98 
 99 int main()
100 {
101     char tmp[50];
102     while(gets(tmp))
103     {
104         node beg;
105         int cnt = 0;
106         for(int i = 0; tmp[i]; i++)
107         {
108             if(tmp[i]==' ') continue;
109             if(tmp[i]=='x') beg.s[cnt] = 9, beg.loc = cnt++;
110             else  beg.s[cnt++] = tmp[i]-'0';
111 
112         }
113         int i = bfs(beg);
114         if(i==-1)
115             puts("unsolvable");
116         else
117             Print(i), putchar('\n');
118     }
119 }
View Code

 

代码二(推荐):把pre和path放在结构体外,利用当前状态status追溯上一个状态status:

POJ1077  Eight —— 正向BFS_i++POJ1077  Eight —— 正向BFS_i++_02
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <vector>
  7 #include <queue>
  8 #include <stack>
  9 #include <map>
 10 #include <string>
 11 #include <set>
 12 #define ms(a,b) memset((a),(b),sizeof((a)))
 13 using namespace std;
 14 typedef long long LL;
 15 const int INF = 2e9;
 16 const LL LNF = 9e18;
 17 const int MOD = 1e9+7;
 18 const int MAXN = 1e6+10;
 19 #define AIM  1     //123456789的哈希值为1
 20 
 21 struct node
 22 {
 23     int status;
 24     int s[9];
 25     int loc;
 26 };
 27 
 28 int vis[MAXN], fac[9] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320};
 29 int dir[4][2] = { -1,0, 1,0, 0,-1, 0,1 };
 30 char op[4] = {'u', 'd', 'l', 'r'  };
 31 char path[MAXN];
 32 int pre[MAXN];
 33 
 34 int cantor(int s[])  //获得哈希函数值
 35 {
 36     int sum = 0;
 37     for(int i = 0; i<9; i++)
 38     {
 39         int num = 0;
 40         for(int j = i+1; j<9; j++)
 41             if(s[j]<s[i])
 42                 num++;
 43         sum += num*fac[8-i];
 44     }
 45     return sum+1;
 46 }
 47 
 48 queue<node>que;
 49 bool bfs(node now)
 50 {
 51     ms(vis,0);
 52     while(!que.empty()) que.pop();
 53 
 54     now.status = cantor(now.s);
 55     pre[now.status] = -1;   //开始状态的上一个状态为-1,用于输出路径时“刹车”
 56     vis[now.status] = 1;
 57     que.push(now);
 58 
 59     node tmp;
 60     while(!que.empty())
 61     {
 62         now = que.front();
 63         que.pop();
 64         if(now.status==AIM) //找到了123456789的状态
 65             return true;
 66 
 67         int x = now.loc/3;
 68         int y = now.loc%3;
 69         for(int i = 0; i<4; i++)
 70         {
 71             int xx = x + dir[i][0];
 72             int yy = y + dir[i][1];
 73             if(xx>=0 && xx<=2 && yy>=0 && yy<=2)
 74             {
 75                 tmp = now;
 76                 tmp.s[x*3+y] = tmp.s[xx*3+yy];  //交换位置,下同
 77                 tmp.s[xx*3+yy] = 9;
 78                 tmp.status = cantor(tmp.s);
 79                 if(!vis[tmp.status])
 80                 {
 81                     vis[tmp.status] = 1;
 82                     tmp.loc = xx*3+yy;
 83                     pre[tmp.status] = now.status;   //tmp.status的上一个状态为now.status
 84                     path[tmp.status] = op[i];   //保存操作
 85                     que.push(tmp);
 86                 }
 87             }
 88         }
 89     }
 90     return 0;
 91 }
 92 
 93 void Print(int status)
 94 {
 95     if(pre[status]==-1) return;
 96     Print(pre[status]);     //追溯上一个状态
 97     putchar(path[status]);
 98 }
 99 
100 int main()
101 {
102     char str[50];
103     while(gets(str))
104     {
105         node now;
106         int cnt = 0;
107         for(int i = 0; str[i]; i++)
108         {
109             if(str[i]==' ') continue;
110             if(str[i]=='x') now.s[cnt] = 9, now.loc = cnt++;
111             else  now.s[cnt++] = str[i]-'0';
112         }
113         if(!bfs(now))
114             puts("unsolvable");
115         else
116             Print(AIM), putchar('\n');
117     }
118 }
View Code