zoukankan      html  css  js  c++  java
  • 八数码问题

    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("
    ");
            }
            else
                printf("unsolvable
    ");
        }
    }

    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
    ");
                continue;
            }
            if (way[index].empty())
                printf("unsolvable
    ");
            else
            {
                for (int i = way[index].size() - 1; i >=0; i--)
                    printf("%c", way[index][i]);
                printf("
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    把VB.NET代码转换为C#代码的方法
    离散数学 第二章 谓词逻辑 26 前束范式
    离散数学 第二章 谓词逻辑 27 谓词演算的推理理论
    asp.net中怎样用Javascript控制RequiredFieldValidator控件什么时候启用,什么时候不启用验证?
    离散数学中的IFF标记
    BIRT Overview
    离散数学 第二章 谓词逻辑 25 谓词演算的等价式和蕴涵式
    getRemoteAddr()和getRemoteHost()的区别
    scp 不用密码
    利用spring实现javamail功能
  • 原文地址:https://www.cnblogs.com/joeylee97/p/7356217.html
Copyright © 2011-2022 走看看