1077 Eight

Eight
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 37738   Accepted: 15932   Special Judge

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: 
 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: 
 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. 

Input

You will receive a description of a configuration of the 8 puzzle. The 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

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.

Sample Input

 2  3  4  1  5  x  7  6  8 

Sample Output

ullddrurdllurdruldr

Source

 
年轻人的第一道A* 答案可能多解
我的这个程序输入样例输入得到的输出是 ldruullddrurdllurrd
跟样例输出不一样 搞的我郁闷了半天
 
注意方向的选取 还有位置的选择
它是
1 2 3
4 5 6
7 8 9
 
康拓展开
类似哈希 给定一个排列组合的数  如123456789 怎么去判定有没有遍历过这个数 可以用康拓展开 八数码问题有9位 直接开1e9的数组可能爆内存 并且有很多数字是用不到的 因为每个数字只出现一次 可能会有123456789 但是绝对不会出现123456788 以此类推 这样浪费了很多空间
由此引出康拓展开 由这个数是第几小的数来作表示 对N个不同的数的排列组合 一共有N!种排列组合 他们的大小都不一样 所以只需要N!的空间就足够存放所有的状态
要注意自己定义的康拓的范围
其中 递增顺序排列是最小的数 即123456789  987654321是最大的数
我这里写的是goal = 1,  所以 cantor是返回v+1避免出现0, 要是 goal = 0, 则cantor返回v就行了 以此类推
记忆方法: 只要记住顺序排列是最小的 它的v是最小的 在以下代码片中要让return v+1 等于1 容易知道下划线部分应该填  ar[j] < ar[i]
int contor(int ar[]) {
    int v = 0;
    for (int i = 0; i < 9; i++) {
        int num = 0;
        for (int j = i + 1; j < 9; j++) {
            if (_______) num++;
        }
        v += num * fac[8 - i];
    }
    return v + 1;
}
 
还有个注意点是曼哈顿距离不算x点
短即是正义 我短我骄傲
  1 #include <stdio.h>
  2 #include <queue>
  3 #include <algorithm>
  4 using namespace std;
  5 int fac[10];
  6 int dx[4] = {-1, 1, 0, 0};
  7 int dy[4] = {0,  0, 1, -1};
  8 char d[4] = {'u','d','r','l'};
  9 const int goal = 1, maxv = 4e5;
 10 bool vis[maxv];
 11 int pre[maxv];
 12 char dir[maxv];
 13 int dish(int ar[]) {
 14     int dis = 0;
 15     for (int i = 0; i < 9; i++) {
 16         if (ar[i] == 9) continue;
 17         int v = ar[i] - 1;
 18         int rx = i / 3, ry = i % 3;
 19         int x = v / 3, y = v % 3;
 20         dis += abs(x - rx) + abs(ry - y);
 21     }
 22     return dis;
 23 }
 24 int contor(int ar[]) {
 25     int v = 0;
 26     for (int i = 0; i < 9; i++) {
 27         int num = 0;
 28         for (int j = i + 1; j < 9; j++)  if (ar[j] < ar[i]) num++;
 29         
 30         v += num * fac[8 - i];
 31     }
 32     return v + 1;
 33 }
 34 struct node {
 35     int g, h, f, sta, xpos;
 36     int s[9];
 37     void init() {
 38         g++; h=dish(s); f=h+g; sta=contor(s);
 39     }
 40     bool operator < (const node x)const {
 41         return f > x.f;
 42     }
 43 };
 44 priority_queue<node> q;
 45 bool Astar(node now) {
 46     fill(vis, vis + maxv, 0);
 47     while (!q.empty()) q.pop();
 48     now.g = -1;
 49     now.init();
 50     q.push(now);
 51     pre[now.sta] = -1;
 52     vis[now.sta] = 1;
 53     while (!q.empty()){
 54         now = q.top(); q.pop();
 55         if (now.sta == goal) return true;
 56         int xpos = now.xpos;
 57         int x = xpos / 3, y = xpos % 3;
 58         for (int i = 0; i < 4; i++) {
 59             int tx = x + dx[i];
 60             int ty = y + dy[i];
 61             if (tx < 0 || ty < 0 || tx >= 3 || ty >= 3) continue;
 62             int newp = tx * 3 + ty;
 63             node tp = now;
 64             tp.xpos = newp;
 65             swap(tp.s[newp], tp.s[xpos]);
 66             tp.init();
 67             
 68             if (vis[tp.sta]) continue;
 69             vis[tp.sta] = 1;
 70             pre[tp.sta] = now.sta;
 71             dir[tp.sta] = d[i];
 72             q.push(tp);
 73         }
 74     }
 75     return false;
 76 }
 77 void Print(int sta) {
 78     if (pre[sta] == -1) return;
 79     Print(pre[sta]);
 80     printf("%c", dir[sta]);
 81 }
 82 int main() {
 83     fac[0] = 1;
 84     for (int i = 1; i < 10; i++) fac[i] = i * fac[i - 1];
 85     char str[30];
 86     while (gets(str)) {
 87         int cnt = 0;
 88         node now;
 89         for (int i = 0; str[i]; i++) {
 90             if (str[i] == ' ') continue;
 91             if (str[i] == 'x') {
 92                 now.xpos = cnt;
 93                 now.s[cnt++] = 9;
 94             }
 95             else
 96                 now.s[cnt++] = str[i] - '0';
 97         }
 98         if (Astar(now)) Print(goal);
 99         else printf("unsolvable");
100         printf("
");
101     }
102     return 0;
103 }
 
原文地址:https://www.cnblogs.com/smatrchen/p/10594723.html