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;
    }

  • 相关阅读:
    sublime开启vim模式
    git命令行界面
    搬进Github
    【POJ 2886】Who Gets the Most Candies?
    【UVA 1451】Average
    【CodeForces 625A】Guest From the Past
    【ZOJ 3480】Duck Typing
    【POJ 3320】Jessica's Reading Problemc(尺取法)
    【HDU 1445】Ride to School
    【HDU 5578】Friendship of Frog
  • 原文地址:https://www.cnblogs.com/CKboss/p/3351098.html
Copyright © 2011-2022 走看看