zoukankan      html  css  js  c++  java
  • BFS 写的8数码问题 POJ 1077

    继8皇后问题后又一大突破8数码问题
    Eight

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other)
    Total Submission(s) : 8   Accepted Submission(s) : 4
    Special Judge
    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: 
    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
    PKU
     



    整个程序由一下几个部分构成:结点,cantor展开(当HASH函数用的),移动函数,BFS,输出函数


     #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <stdio.h>

    #define MAX 500000

    char str[400000];
        int tot=0;

    using namespace std;

    struct Note
    {
        char s[9];//数码串
        int num;//第多少号
        int fa;//父结点是多少号
        char dir;//从父结点MOVE方向
    }note[MAX];

    queue<Note> q;

    int vis[MAX];

    int cantor(char* s)
    {
        int len=9;

        int sum=0;
        for(int i=0;i<len;i++)
        {
            int a=0;
            int b=1;
            for(int j=i+1;j<len;j++)
                if(s[j]<s)
                {
                    a=a+1;
                }
            //sum+=a*(8-i)!
            for(int k=1;k<len-i;k++)
            {
                b*=k;
            }

            sum+=a*b;
        }

        return sum;

    }

    int move4(char *s,int n)
    {
        //会对S进行改变
        //返回1表示进行了移动,返回0表示没有移动
        int pos;
        int len=9;
        if(n==1)//move up
        {
            for(int i=0;i<len;i++)
            {
                if(s=='9')
                {
                    pos=i;
                    break;
                }
            }
            if(pos-3>=0)
            {
                s[pos]=s[pos-3]^s[pos];
                s[pos-3]=s[pos]^s[pos-3];
                s[pos]=s[pos]^s[pos-3];

                return 1;
            }
            else
                return 0;
        }
        if(n==2)//move down
        {
            for(int i=0;i<len;i++)
            {
                if(s=='9')
                {
                    pos=i;
                    break;
                }
            }
            if(pos+3<9)
            {
                s[pos]=s[pos+3]^s[pos];
                s[pos+3]=s[pos]^s[pos+3];
                s[pos]=s[pos]^s[pos+3];

                return 1;
            }
            else
                return 0;
        }
        if(n==3)//move left
        {
            for(int i=0;i<len;i++)
            {
                if(s=='9')
                {
                    pos=i;
                    break;
                }
            }
            if(pos-1>=0&&(pos/3==(pos-1)/3))
            {
                s[pos]=s[pos-1]^s[pos];
                s[pos-1]=s[pos]^s[pos-1];
                s[pos]=s[pos]^s[pos-1];

                return 1;
            }
            else
                return 0;
        }
        if(n==4)//move right
        {
            for(int i=0;i<len;i++)
            {
                if(s=='9')
                {
                    pos=i;
                    break;
                }
            }
            if(pos+1<9&&(pos/3==(pos+1)/3))
            {
                s[pos]=s[pos+1]^s[pos];
                s[pos+1]=s[pos]^s[pos+1];
                s[pos]=s[pos]^s[pos+1];

                return 1;
            }
            else
                return 0;
        }

        return 0;
    }

    int bfs()
    {
        while(!q.empty())
        {
            int ok=1;
            Note t=q.front();
            Note t2=q.front();
            q.pop();
            for(int i=0;i<8;i++)
            {
                if(t.s-48==i+1&&t.s[8]=='9')
                       ;
                else
                    {
                        ok=0;
                    }
            }
     //       cout<<"判断是否可以结束:  "<<ok<<endl;

            if(ok)
            {
                return t.fa;
            }
     //           cout<<"还要继续搜索。。。"<<endl;
                t2=t;//cout<<"up up up\n";
                if(move4(t2.s,1))
                {
       //             cout<<"向上走。。。"<<endl;

                    int k=cantor(t2.s);
                    if(vis[k]==0)
                    {
     //                   cout<<"行。。。"<<endl;
                        t2.dir='u';
                        t2.fa=t.num;
    /*
                        cout<<"k: "<<k<<" fa:"<<t2.fa<<endl;
                        for(int i=0;i<9;i++)
                        {
                            cout<<t2.s<<" ";
                            if((i+1)%3==0) cout<<endl;
                        }
                        cout<<t2.dir<<endl;

    */
                        t2.num=k;
                        note[k]=t2;
                        q.push(t2);
                        vis[k]=1;
                    }
      //              else cout<<"不行。。。"<<endl;
                }
                t2=t; // cout<<"down down down\n";
                if(move4(t2.s,2))
                {
      //              cout<<"向下走。。。"<<endl;

                    int k=cantor(t2.s);
                    if(vis[k]!=1)
                    {
                        t2.dir='d';
                        t2.fa=t.num;
      //                   cout<<"行。。。"<<endl;
    /*
                        cout<<"k: "<<k<<" fa:"<<t2.fa<<endl;
                        for(int i=0;i<9;i++)
                        {
                            cout<<t2.s<<" ";
                            if((i+1)%3==0) cout<<endl;
                        }
                        cout<<t2.dir<<endl;
    */
                        t2.num=k;
                        note[k]=t2;
                        q.push(t2);
                        vis[k]=1;
                    }
      //              else cout<<"不行。。。"<<endl;
                }
                t2=t; // cout<<"left left left\n";
                if(move4(t2.s,3))
                {
      //              cout<<"向左走。。。"<<endl;

                    int k=cantor(t2.s);
                    if(vis[k]!=1)
                    {
                        t2.dir='l';
                        t2.fa=t.num;
        //                 cout<<"行。。。"<<endl;
    /*
                        cout<<"k: "<<k<<" fa:"<<t2.fa<<endl;
                        for(int i=0;i<9;i++)
                        {
                            cout<<t2.s<<" ";
                            if((i+1)%3==0) cout<<endl;
                        }
                        cout<<t2.dir<<endl;

      */                  t2.num=k;
                        note[k]=t2;
                        q.push(t2);
                        vis[k]=1;
                    }
       //            else cout<<"不行。。。"<<endl;
                }
                t2=t; //cout<<"right right right\n";
                if(move4(t2.s,4))
                {
       //             cout<<"向右走。。。"<<endl;

                    int k=cantor(t2.s);
                    if(vis[k]!=1)
                    {
                        t2.dir='r';
                        t2.fa=t.num;
                        // cout<<"行。。。"<<endl;

    /*
                        cout<<"k: "<<k<<" fa:"<<t2.fa<<endl;
                        for(int i=0;i<9;i++)
                        {
                            cout<<t2.s<<" ";
                            if((i+1)%3==0) cout<<endl;
                        }
                        cout<<t2.dir<<endl;
    */
                        t2.num=k;
                        note[k]=t2;
                        q.push(t2);
                        vis[k]=1;
                    }
      //              else cout<<"不行。。。"<<endl;
                }

        }

        return -999;
    }


    void print (int p)
    {
        stack < char > stck;
        while ( note[p].dir!='Q' )
        {
            stck.push(note[p].dir);
            p = note[p].fa;
        }
        while ( !stck.empty() )
        {
            putchar ( stck.top() );
            stck.pop();
        }
        putchar ('\n');
    }


    int main()
    {
        memset(vis,0,sizeof(vis));
        Note t;
        for(int i=0;i<9;i++)
        {
            char c;
            cin>>c;
            if(c=='x')
            {
                t.s='9';
            }
            else t.s=c;
        }

        int k=cantor(t.s);
        t.num=k;
        t.fa=-998;
        t.dir='Q';
        note[k]=t;

        q.push(t);

        int B=bfs();
        note[k].dir='Q';
        note[k].fa=-998;
        ///xxxxxx
        if(B==-999)  cout<<"unsolvable"<<endl;

      //  cout<<"B:  "<<B<<endl;

        print(0);

        return 0;
    }

  • 相关阅读:
    yum与rpm常用命令
    centos7更改时区,同步时间
    剑指Offer45:扑克牌顺子(java)
    剑指Offer44:翻转单词顺序列(java)
    剑指Offer43:左旋转字符串(Java)
    剑指Offer42:和为S的两个数字(java)
    剑指Offer41:和为S的连续正数序列(Java)
    剑指Offer39:平衡二叉树(Java)
    剑指Offer40:数组中只出现一次的数字(Java)
    剑指Offer38:二叉树的深度(Java)
  • 原文地址:https://www.cnblogs.com/CKboss/p/3351098.html
Copyright © 2011-2022 走看看