八数码问题

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. 

InputYou 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 
OutputYou 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. 
Sample Input

2  3  4  1  5  x  7  6  8

Sample Output

ullddrurdllurdruldr

1. BFS + 康托展开 + Hash
超时
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<sstream>
#include<algorithm>
#include<queue>
#include<deque>
#include<iomanip>
#include<vector>
#include<cmath>
#include<map>
#include<stack>
#include<set>
#include<memory>
#include<list>
#include<string>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define MAXN 15
#define L 663000
#define INF 1000000009
#define eps 0.00000001
/*
八数码问题
解法1.康托展开+Hash+BFS
*/
struct node
{
    int data[MAXN];
    int Hash, pos;
    vector<char> path;
};

int  fac[] = { 1,1,2,6,24,120,720,5040,40320 };
int Aim[] = { 1,2,3,4,5,6,7,8,0 };
int beg[MAXN], aim;
bool vis[L];
node ans;

int Kt(int n, int tmp[])
{
    int  sum = 0, t;
    for (int i = 0; i < n; i++)
    {
        t = 0;
        for (int j = i + 1; j < n; j++)
        {
            if (tmp[j] < tmp[i])
                t++;
        }
        sum += fac[n - i - 1] * t;
    }
    return sum;
}

bool bfs()
{
    node t;
    queue<node> q;
    memcpy(t.data, beg, sizeof(beg));
    t.path.clear();
    t.Hash = Kt(9, t.data);
    for (int i = 0; i < 9; i++)
        if (t.data[i] == 0)
            t.pos = i;
    vis[t.Hash] = true;
    q.push(t);
    while (!q.empty())
    {
    //    cout << 1 << endl;
        node f = q.front();
        q.pop();
        if (f.Hash == aim)
        {
            ans = f;
            return true;
        }
        if ((f.pos + 1) % 3 != 0)
        {
            t = f;
            swap(t.data[t.pos], t.data[t.pos + 1]);
            int H = Kt(9, t.data);
            if (!vis[H])
            {
                vis[H] = true;
                t.pos = t.pos + 1;
                t.Hash = H;
                t.path.push_back('r');
                q.push(t);
            }
        }
        if (f.pos % 3 != 0)
        {
            t = f;
            swap(t.data[t.pos], t.data[t.pos - 1]);
            int H = Kt(9, t.data);
            if (!vis[H])
            {
                vis[H] = true;
                t.pos--;
                t.Hash = H;
                t.path.push_back('l');
                q.push(t);
            }
        }
        if (f.pos > 2)
        {
            t = f;
            swap(t.data[t.pos], t.data[t.pos - 3]);
            int H = Kt(9, t.data);
            if (!vis[H])
            {
                vis[H] = true;
                t.pos = t.pos - 3;
                t.Hash = H;
                t.path.push_back('u');
                q.push(t);
            }
        }
        if (t.pos < 6)
        {
            t = f;
            swap(t.data[t.pos], t.data[t.pos + 3]);
            int H = Kt(9, t.data);
            if (!vis[H])
            {
                vis[H] = true;
                t.pos = t.pos + 3;
                t.Hash = H;
                t.path.push_back('d');
                q.push(t);
            }
        }
    }
    return false;
}

int main()
{
    aim = Kt(9, Aim);
    char c[2];
    while (scanf("%s", c))
    {
        memset(vis, false, sizeof(vis));
        if (c[0] == 'x') beg[0] = 0;
        else beg[0] = c[0] - '0';
        for (int i = 1; i < 9; i++)
        {
            scanf("%s", c);
            if (c[0] == 'x') beg[i] = 0;
            else beg[i] = c[0] - '0';
        }
        if (bfs())
        {
            for (int i = 0; i < ans.path.size(); i++)
            {
                printf("%c", ans.path[i]);
            }
            printf("\n");
        }
        else
            printf("unsolvable\n");
    }
}

2. 

反向打表查询 

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<sstream>
#include<algorithm>
#include<queue>
#include<deque>
#include<iomanip>
#include<vector>
#include<cmath>
#include<map>
#include<stack>
#include<set>
#include<memory>
#include<list>
#include<string>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define MAXN 363000
#define INF 1000000009
#define eps 0.00000001
/*
反向搜索 打表查询
*/
int fac[10] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320}, a;
bool vis[MAXN];
vector<char> way[MAXN];
struct node
{
    int pos;
    int data[10];
    int Hash;
    vector<char> path;
};
int Kt(int s[])
{
    int sum = 0;
    for (int i = 0; i < 9; i++)
    {
        int t = 0;
        for (int j = i + 1; j < 9; j++)
        {
            if (s[j] < s[i])
                t++;
        }
        sum += fac[8 - i] * t;
    }
    return sum + 1;
}
int x[4] = { 1,-1, 3, -3 };
char d[5] = "lrud";
bool check(int tp, int ti)
{
    if (ti == 0)
        return (tp + 1) % 3 != 0;
    else if (ti == 1)
        return tp % 3 != 0;
    else if (ti == 2)
        return tp < 6;
    else
        return tp > 2;
}
void bfs()
{
    int aim[10] = { 1,2,3,4,5,6,7,8,0 };
    node t;
    queue<node> q;
    memcpy(t.data, aim, sizeof(aim));
    t.Hash = Kt(t.data);
    t.pos = 8;
    t.path.clear();
    vis[t.Hash] = true;
    a = t.Hash;
    q.push(t);
    while (!q.empty())
    {
        node f = q.front();
        q.pop();
        for (int i = 0; i < 4; i++)
        {
            if (!check(f.pos, i))
                continue;
            t = f;
            int np = t.pos + x[i];
            swap(t.data[t.pos], t.data[np]);
            int H = Kt(t.data);
            if (!vis[H])
            {
                vis[H] = true;
                t.pos = np;
                t.Hash = H;
                t.path.push_back(d[i]);
                way[H] = t.path;
                q.push(t);
            }
        }
    }
}
int q[11];
int main()
{
    bfs();
    char c[2];
    while (scanf("%s", c) != EOF)
    {
        if (c[0] != 'x') q[0] = c[0] - '0';
        else    q[0] = 0;
        for (int i = 1; i < 9; i++)
        {
            scanf("%s", c);
            if (c[0] != 'x') q[i] = c[0] - '0';
            else    q[i] = 0;
        }
        int index = Kt(q);
        if (index == a)
        {
            printf("lr\n");
            continue;
        }
        if (way[index].empty())
            printf("unsolvable\n");
        else
        {
            for (int i = way[index].size() - 1; i >=0; i--)
                printf("%c", way[index][i]);
            printf("\n");
        }
    }
    return 0;
}

 

posted @ 2017-08-14 09:54  joeylee97  阅读(141)  评论(0编辑  收藏  举报