zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    蓝桥杯 矩阵翻硬币
    2018 南京预选赛 J Sum ( 欧拉素数筛 、Square-free Number、DP )
    HDU 3826 Squarefree number ( 唯一分解定理 )
    HDU 5727 Necklace ( 2016多校、二分图匹配 )
    HDU 5726 GCD (2016多校、二分、ST表处理区间GCD、数学)
    hihocoder 1457 后缀自动机四·重复旋律7 ( 多串连接处理技巧 )
    后缀自动机 ( SAM ) 模板
    2018 焦作网络赛 K Transport Ship ( 二进制优化 01 背包 )
    2018 焦作网络赛 G Give Candies ( 欧拉降幂 )
    蓝桥杯 买不到的数目 ( 裴蜀定理 )
  • 原文地址:https://www.cnblogs.com/veasky/p/11011525.html
Copyright © 2011-2022 走看看