HDU1043 Eight

题目:

简单介绍一下八数码问题:
        在一个3×3的九宫格上,填有1~8八个数字,空余一个位置,例如下图:

1 2 3
4 5 6
7 8  

        在上图中,由于右下角位置是空的,你可以移动数字,比如可以将数字6下移一位:

1 2 3   1 2 3
4 5 6 4 5  
7 8     7 8 6

        或者将数字8右移一位:

1 2 3   1 2 3
4 5 6 4 5 6
7 8     7   8

        1~8按顺序排列的情况称为“初始状态”(如最上方图)。“八数码问题”即是求解对于任意的布局,将其移动至“初始状态”的方法。 
        给定一个现有的九宫格布局,请输出将它移动至初始状态的移动方法的步骤。

输入:

 输入包含多组数据,处理至文件结束。每组数据占一行,包含8个数字和表示空位的‘x’,各项以空格分隔,表示给定的九宫格布局。 
        例如,对于九宫格

1 2 3
  4 6
7 5 8

        输入应为:1 2 3 x 4 6 7 5 8

 输出:

对于每组输入数据,输出一行,即移动的步骤。向上、下、左、右移动分别用字母u、d、l、r表示;如果给定的布局无法移动至“初始 状态”,请输出unsolvable。
        如果有效的移动步骤有多种,输出任意即可。

样例:

分析:双向BFS,简单来说就是同时进行两个BFS,但每个BFS的vis数组有了新的用途即判断另一个BFS是否达到此BFS扩展到的此刻的点,若抵达即连通。

unsolvable的情况用逆序数的奇偶性判断,因为目标状态12345678逆序数为0,所以当前态的逆序数必为偶

用康托展开记录字典序用于状态压缩(hash)

  1 #include<iostream>
  2 #include<sstream>
  3 #include<cstdio>
  4 #include<cstdlib>
  5 #include<string>
  6 #include<cstring>
  7 #include<algorithm>
  8 #include<functional>
  9 #include<iomanip>
 10 #include<numeric>
 11 #include<cmath>
 12 #include<queue>
 13 #include<vector>
 14 #include<set>
 15 #include<cctype>
 16 #define PI acos(-1.0)
 17 const int INF = 0x3f3f3f3f;
 18 const int NINF = -INF - 1;
 19 typedef long long ll;
 20 using namespace std;
 21 int fac[10] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
 22 int vis1[362885], vis2[362885];
 23 int eda[9]={ 1, 2, 3, 4, 5, 6, 7, 8, 0};
 24 string path[362885];
 25 int dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, -1, 1};
 26 char p1[4] = {'d', 'u', 'l', 'r'}, p2[4] = {'u', 'd', 'r', 'l'};
 27 struct node
 28 {
 29     int s[9];
 30     int cur, n;//cur目前x所在位置,n为hash值
 31 }st;
 32 int cantor(int *s)//康托展开
 33 {
 34     int sum = 1;
 35     for (int i = 0;i < 9; ++i)
 36     {
 37         int k = 0;
 38         for (int j = i + 1; j < 9; ++j)
 39             if( s[j] < s[i]) k++;
 40         sum += k * fac[8 - i];
 41     }
 42     return sum;
 43 }
 44 void bfs()
 45 {
 46     memset(vis1, 0, sizeof(vis1));
 47     memset(vis2, 0, sizeof(vis2));
 48     queue<node> q1, q2;
 49     st.n = cantor(st.s);
 50     q1.push(st);
 51     vis1[st.n] = 1;
 52     path[st.n] = "";//重要
 53     node ed;
 54     memcpy(ed.s, eda, sizeof(ed.s));
 55     ed.n = cantor(ed.s);
 56     ed.cur = 8;
 57     path[ed.n] = "";
 58     q2.push(ed);
 59     vis2[ed.n] = 1;
 60     while (q1.size() || q2.size())
 61     {
 62         node temp1 = q1.front();
 63         q1.pop();
 64         int x1 = temp1.cur / 3, y1 = temp1.cur % 3;
 65         for (int i = 0; i < 4; ++i)
 66         {
 67             int nx = x1 + dx[i], ny = y1 + dy[i];
 68             if (nx < 0 || nx > 2 || ny < 0 || ny > 2) continue;
 69             node rec = temp1;
 70             rec.cur = nx * 3 + ny;
 71             swap(rec.s[temp1.cur], rec.s[rec.cur]);
 72             rec.n = cantor(rec.s);
 73             if (vis2[rec.n])
 74             {
 75                 reverse(path[rec.n].begin(), path[rec.n].end());
 76                 cout << path[temp1.n] << p1[i] << path[rec.n] << endl;
 77                 return;
 78             }
 79             if (!vis1[rec.n])
 80             {
 81                 vis1[rec.n] = 1;
 82                 path[rec.n] = path[temp1.n];
 83                 path[rec.n] += p1[i];
 84                 q1.push(rec);
 85             }
 86         }
 87         node temp2 = q2.front();
 88         q2.pop();
 89         int x2 = temp2.cur / 3, y2 = temp2.cur % 3;
 90         for (int i = 0; i < 4; ++i)
 91         {
 92             int nx = x2 + dx[i], ny = y2 + dy[i];
 93             if (nx < 0 || nx > 2 || ny < 0 || ny > 2) continue;
 94             node rec = temp2;
 95             rec.cur = nx * 3 + ny;
 96             swap(rec.s[temp2.cur], rec.s[rec.cur]);
 97             rec.n = cantor(rec.s);
 98             if (vis1[rec.n])
 99             {
100                 reverse(path[temp2.n].begin(), path[temp2.n].end());
101                 cout << path[rec.n] << p2[i] << path[temp2.n] << endl;
102                 return;
103             }
104             if (!vis2[rec.n])
105             {
106                 vis2[rec.n] = 1;
107                 path[rec.n] = path[temp2.n];
108                 path[rec.n] += p2[i];
109                 q2.push(rec);
110             }
111         }
112     }
113 }
114 
115 int main()
116 {
117     char c;
118     while(cin >> c)
119     {
120         if(c == 'x')
121         {
122             st.s[0] = 0;
123             st.cur = 0;
124         }
125         else st.s[0] = c - '0';
126         for (int i = 1; i < 9; ++i)
127         {
128             cin >> c;
129             if ( c == 'x')
130             {
131                 st.s[i] = 0;
132                 st.cur = i;
133             }
134             else st.s[i] = c - '0';
135         }
136         int k = 0;
137         for(int i = 0; i < 8; ++i)
138         {
139             if (st.s[i])
140             {
141                 for (int j = i + 1; j < 9; ++j)
142                     if (st.s[j] < st.s[i] && st.s[j]) k++;
143             }
144         }
145         if(k & 1) cout<< "unsolvable" << endl;
146         else bfs();
147     }
148     return 0;
149 }

 

posted @ 2019-06-12 18:47  Veasky  阅读(620)  评论(0编辑  收藏  举报