博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BFS 写的8数码问题 POJ 1077
阅读量:4340 次
发布时间:2019-06-07

本文共 6165 字,大约阅读时间需要 20 分钟。

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

转载于:https://www.cnblogs.com/CKboss/archive/2013/04/13/3351098.html

你可能感兴趣的文章
求一个数的整数次方
查看>>
点云PCL中小细节
查看>>
铁路信号基础
查看>>
RobotFramework自动化2-自定义关键字
查看>>
[置顶] 【cocos2d-x入门实战】微信飞机大战之三:飞机要起飞了
查看>>
BABOK - 需求分析(Requirements Analysis)概述
查看>>
第43条:掌握GCD及操作队列的使用时机
查看>>
Windows autoKeras的下载与安装连接
查看>>
CMU Bomblab 答案
查看>>
微信支付之异步通知签名错误
查看>>
2016 - 1 -17 GCD学习总结
查看>>
linux安装php-redis扩展(转)
查看>>
Vue集成微信开发趟坑:公众号以及JSSDK相关
查看>>
技术分析淘宝的超卖宝贝
查看>>
i++和++1
查看>>
react.js
查看>>
P1313 计算系数
查看>>
NSString的长度比较方法(一)
查看>>
Azure云服务托管恶意软件
查看>>
My安卓知识6--关于把项目从androidstudio工程转成eclipse工程并导成jar包
查看>>