zoukankan      html  css  js  c++  java
  • HDU 1043 Eight(八数码)

    HDU 1043 Eight(八数码)

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

     

    Problem Description - 题目描述
      The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've seen it. It is constructed with 15 sliding tiles, each with a number from 1 to 15 on it, and all packed into a 4 by 4 frame with one tile missing. Let's call the missing tile 'x'; the object of the puzzle is to arrange the tiles so that they are ordered as:
    15-puzzle有着超过100年的历史;就算没听过,估计也见过。它由15片滑块组成,各块标有数字1到15,并且全都装在一个4 x 4的边框里,防止哪块突然丢了。空块为’x’;这道题的目标是排列滑块使之顺序如下:
    CN
     1  2  3  4
     5  6  7  8
     9 10 11 12
    13 14 15  x
    
     

      where the only legal operation is to exchange 'x' with one of the tiles with which it shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle:

    唯一的合法操作是将’x’与其共边的滑块交换。例子如下,通过一系列移动解决一个被稍微打乱的问题。
    CN
     1  2  3  4     1  2  3  4     1  2  3  4     1  2  3  4
     5  6  7  8     5  6  7  8     5  6  7  8     5  6  7  8
     9  x 10 12     9 10  x 12     9 10 11 12     9 10 11 12
    13 14 11 15    13 14 11 15    13 14  x 15    13 14 15  x
                r->            d->            r->
    

      The letters in the previous row indicate which neighbor of the 'x' tile is swapped with the 'x' tile at each step; legal values are 'r','l','u' and 'd', for right, left, up, and down, respectively.

      Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, and frustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing 'x' tile, of course).

      In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three arrangement.

    上一行的字母表示每次’x’与哪块相邻的滑块交换;有效值'r''l''u''d'分别表示右、左、上、下。
    
    并非所有情况都有解;在1870年,一个叫Sam Loyd的人就以发布了一个无解版本而出名,成功地难住了许多人。实际上,要制造无解的情况只需交换两个滑块(当然是非’x’滑块)。
    
    这个问题中,你需要写个程序解决著名的八数码问题,滑块为三行三列。
    CN
    Input - 输入

      You will receive, several descriptions of configuration of the 8 puzzle. One description is just a list of the tiles in their initial positions, with the rows listed from top to bottom, and the tiles listed from left to right within a row, where the tiles are represented by numbers 1 to 8, plus 'x'. For example, this puzzle

    1 2 3

    x 4 6

    7 5 8

      is described by this list:

    1 2 3 x 4 6 7 5 8

    你会得到若干个八数码的配置描述。每个描述都是一个滑块初始位置的列表,从上往下,从左往右,使用数字1到8,还有’x’表示。比如,
    
    1 2 3 
    x 4 6 
    7 5 8 
    
    描述如下:
    
    1 2 3 x 4 6 7 5 8
    CN


    Output - 输出

      You will print to standard output either the word ``unsolvable'', if the puzzle has no solution, or a string consisting entirely of the letters 'r', 'l', 'u' and 'd' that describes a series of moves that produce a solution. The string should include no spaces and start at the beginning of the line. Do not print a blank line between cases.
    如果无解,输出”unsolvable''”,否则输出一个仅由'r', 'l', 'u''d' 组成的字符串,描述求解的步骤。这个字符串不含空格且单独在一行。用例间别输出空行。
    CN

    Sample Input - 输入样例

    2  3  4  1  5  x  7  6  8
    

     

    Sample Output - 输出样例

    ullddrurdllurdruldr
    

     

    题解
      逼你学新知识系列……(某废渣作死爆内存了……)
      状态可以用全排列表示,用康托展开来压缩状态和去重,然后剩下的只有BFS了……(无聊用了树状数组求逆序数)
      多组输入有点坑……其实如果符合情况直接输出空行也是可以的。

     

    代码 C++

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <queue>
     4 #define MX 362880
     5 #define bitMX 10
     6 
     7 int tre[bitMX];
     8 int lowBit(int a) { return -a&a; }
     9 void add(int i) {
    10     while (i < bitMX) { ++tre[i]; i += lowBit(i); }
    11 }
    12 int sum(int i) {
    13     int opt = 0;
    14     while (i) { opt += tre[i]; i -= lowBit(i); }
    15     return opt;
    16 }
    17 
    18 int ktf[9], data[9];
    19 int preKte() {
    20     int i, j, opt = 0;
    21     memset(tre, 0, sizeof tre);
    22     for (i = 8; ~i; --i) {
    23         opt += sum(data[i])*ktf[i];
    24         add(data[i]);
    25     }
    26     return opt;
    27 }
    28 void kte(int a) {
    29     int i, j, tmp[9];
    30     for (i = 0; i < 9; ++i) tmp[i] = i + 1;
    31     for (i = 0; i < 8; ++i) {
    32         j = a / ktf[i]; a %= ktf[i];
    33         data[i] = tmp[j];
    34         memcpy(tmp + j, tmp + j + 1, sizeof(int)*(8 - j));
    35     }
    36     data[i] = tmp[0];
    37 }
    38 
    39 int lst[MX];
    40 char pre[MX];
    41 void push(int now, int i, int j, char c, std::queue<int> &q) {
    42     data[i] ^= data[j]; data[j] ^= data[i]; data[i] ^= data[j];
    43     int nxt = preKte();
    44     if (!pre[nxt]) {
    45         lst[nxt] = now; pre[nxt] = c;
    46         q.push(nxt);
    47     }
    48     data[i] ^= data[j]; data[j] ^= data[i]; data[i] ^= data[j];
    49 }
    50 void init() {
    51     int i, j, now, nxt;
    52     ktf[7] = 1;
    53     for (i = 6, j = 2; ~i; --i, ++j) ktf[i] = ktf[i + 1] * j;
    54     memset(lst, -1, sizeof lst);
    55     lst[0] = 0; pre[0] = ' ';
    56     std::queue<int> q; q.push(0);
    57     while (!q.empty()) {
    58         now = q.front(); q.pop();
    59         kte(now);
    60         for (i = 0; data[i] != 9; ++i);
    61         if (i > 2) push(now, i, i - 3, 'd', q);
    62         if (i < 6) push(now, i, i + 3, 'u', q);
    63         if (i % 3) push(now, i, i - 1, 'r', q);
    64         if ((i + 1) % 3) push(now, i, i + 1, 'l', q);
    65     }
    66 
    67     
    68 }
    69 int main() {
    70     init();
    71     int i, j;
    72     char red[18];
    73     while (gets(red)) {
    74         for (i = j = 0; i < 18; i += 2, ++j) data[j] = red[i] == 'x' ? 9 : red[i] - '0';
    75         if (~lst[i = preKte()]) {
    76             for (j = i; j; j = lst[j]) putchar(pre[j]);
    77             puts("");
    78         }
    79         else puts("unsolvable");
    80     }
    81     return 0;
    82 }
  • 相关阅读:
    Centos7 KVM启用嵌套虚拟化
    CentOS 桥接网卡配置
    centos iso镜像自动挂载
    git status没有颜色提示
    virt-install 安装系统和启动虚机
    Python 源代码代码打包成 whl 文件
    存储池与存储卷,使用virt-install创建虚拟机
    ftp 搭建 centos 源
    git 生成并添加 SSH key
    linked-list-cycle leetcode C++
  • 原文地址:https://www.cnblogs.com/Simon-X/p/6701038.html
Copyright © 2011-2022 走看看