Eight+POJ+八数码问题+bfs+dbfs+字符串哈希+全排列哈希

Eight
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 24515 Accepted: 10812 Special Judge

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
解决方案:用bfs+字符串哈希靠rp能过,bfs+全排列哈希完全没问题,双向bfs+字符串哈希rp不够,过不了,双向bfs+全排列哈希也没问题,所以全排列哈希比字符串哈希靠谱。这些只能过了POJ上的题,hdu上的还是超时了。
code:bfs+字符串哈希/全排列哈希
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
using namespace std;
char M[20];
int dirx[4]= {1,-1,0,0};
int diry[4]= {0,0,-1,1};
char op[6]="dulr";
char goal[20]="12345678x";
int fact[8]= {1,2,6,24,120,720,5040,40320};
struct path
{
    char op;
    int fa;
} P[600000];///¼Ç¼·¾¶
char Path[600000];///¼Ç¼²Ù×÷
bool vis[600011];
struct node
{
    char M[20];
    int position;
    int op;
    node(char s[],int p,int o)
    {
        for(int i=0; i<9; i++)
            M[i]=s[i];
        M[9]='\0';
        position=p;
        op=o;
    }
    void Swap(int s,int e)
    {
        char temp=M[s];
        M[s]=M[e];
        M[e]=temp;
        position=s;
    }
};

bool judge(char edf[])
{
    for(int i=0; i<9; i++)
    {
        if(edf[i]==goal[i])
        {

        }
        else return false;
    }
    return true;

}
unsigned int BKDRHash(char *str)
{
    unsigned int seed = 131; // 31 131 1313 13131 131313 etc..
    unsigned int hash = 0;

    while (*str)
    {
        hash = hash * seed + (*str++);
    }
    return (hash & 0x7FFFFFFF)%600007;
}///字符串哈希
int code(char s[])
{
    int res=0;
    for(int i=1; i<9; i++)
    {
        int cnt=0;
        for(int j=0; j<i; j++)
        {
            if(s[j]>s[i]) cnt++;
        }
        cnt*=fact[i-1];
        res+=cnt;
    }
    return res;
}///全排列哈希
int main()
{
    while(~scanf(" %c",&M[0]))
    {

        int p;
        if(M[0]=='x') p=0;
        for(int i=1; i<9; i++)
        {
            scanf(" %c",&M[i]);
            if(M[i]=='x') p=i;
        }
        M[9]='\0';
        getchar();
        memset(vis,false,sizeof(vis));
        node temp(M,p,1);
        queue<node >Q;
        Q.push(temp);
        int times=1;
        bool flag=false;
        vis[code(M)]=true;
        while(!Q.empty())
        {
            temp=Q.front();
            Q.pop();
            if(judge(temp.M))
            {
                int j=0;
                int s=temp.op;
                while(s!=1)
                {
                    Path[j++]=P[s].op;
                    s=P[s].fa;
                }
                Path[j]='\0';
                flag=true;
                break;
            }
            int x=temp.position/3,y=temp.position%3;
            for(int i=0; i<4; i++)
            {
                int xx=x+dirx[i];
                int yy=y+diry[i];
                if(xx>=0&&xx<=2&&yy>=0&&yy<=2)
                {
                    int p=3*xx+yy;
                    if(p>=0&&p<=8)
                    {
                        node temp1=temp;
                        temp1.Swap(p,temp.position);
                        int e=code(temp1.M);
                        if(!vis[e])
                        {
                            vis[e]=true;;
                            P[++times].fa=temp.op;
                            P[times].op=op[i];
                            temp1.op=times;
                            Q.push(temp1);
                        }
                    }
                }
            }

        }
        if(flag)
        {
            int len=strlen(Path);
            for(int i=len-1; i>=0; i--)
            {
                printf("%c",Path[i]);
            }
            printf("\n");
        }
        else
        {
            printf("unsolvable\n");
        }
    }
    return 0;
}

code:双dfs+全排列哈希
#include<cstdio>
#include<cstring>
#include<queue>
#include<map>
#include<iostream>
using namespace std;
struct node
{
    char M[20];
    int position;
    node(char s[],int p)
    {
        for(int i=0; i<9; i++)
        {
            M[i]=s[i];
        }
        M[9]='\0';
        position=p;
    }
    void Swap(int e,int p)
    {
        char temp=M[e];
        M[e]=M[p];
        M[p]=temp;
        position=e;
    }
};
int dirx[4]= {1,-1,0,0};
int diry[4]= {0,0,-1,1};
char O[5]="dulr";
char inO[5]="udrl";
int fact[8]={1,2,6,24,120,720,5040,40320};
unsigned int BKDRHash(char *str)
{
    unsigned int seed = 131; // 31 131 1313 13131 131313 etc..
    unsigned int hash = 0;

    while (*str)
    {
        hash = hash * seed + (*str++);
    }
    return (hash & 0x7FFFFFFF)%600013;
}///字符串哈希
int code(char s[]){
  int res=0;
  for(int i=1;i<9;i++){
    int cnt=0;
    for(int j=0;j<i;j++){
        if(s[j]>s[i]) cnt++;
    }
    cnt*=fact[i-1];
    res+=cnt;
  }
  return res;
}///全排列哈希
int vis[600013];
struct node1
{
    int fa;
    char op;
} Op[600013];
void init()
{
    memset(vis,0,sizeof(vis));
    for(int i=0; i<600013; i++)
    {
        Op[i].fa=-1;
    }

}
bool judge(node temp)
{
    node endpoint("12345678x",8);
    for(int i=0; i<9; i++)
    {
        if(temp.M[i]!=endpoint.M[i])
            return false;
    }
    return true;
}
char path[600011];
char path1[600011];
int main()
{
    char M[20];
    while(~scanf(" %c",&M[0]))
    {
        int p;
        if(M[0]=='x')p=0;
        for(int i=1; i<9; i++)
        {
            scanf(" %c",&M[i]);
            if(M[i]=='x') p=i;
        }
        getchar();
        M[9]='\0';
        init();
        node start(M,p);
        node endpoint("12345678x",8);
        queue<node>Q1,Q2;
        int e1=code(M),e2=code(endpoint.M);
        vis[e1]=1,vis[e2]=2;
        Q1.push(start);
        Q2.push(endpoint);
        bool flag=false;
        while(!Q1.empty()&&!Q2.empty())
        {
            node temp=Q1.front();
            Q1.pop();
            if(judge(temp))
            {
                //cout<<"sdf";
                int e=BKDRHash(temp.M);
                int j=0;
                while(Op[e].fa!=-1)
                {
                    path[j++]=Op[e].op;
                    e=Op[e].fa;
                }
                path[j]='\0';
                path1[0]='\0';
                flag=true;
                break;
            }

            int x=temp.position/3,y=temp.position%3;
            for(int i=0; i<4; i++)
            {
                int xx=x+dirx[i];
                int yy=y+diry[i];
                if(xx>=0&&xx<=2&&yy>=0&&yy<=2)
                {
                    int newp=xx*3+yy;
                    if(newp>=0&&newp<=8)
                    {
                        node temp1=temp;
                        temp1.Swap(newp,temp.position);
                        int e=code(temp1.M);
                        int efa=code(temp.M);
                        if(!vis[e])
                        {
                            vis[e]=1;
                            Op[e].fa=efa;
                            Op[e].op=O[i];
                            Q1.push(temp1);
                        }
                        else if(vis[e]==2)
                        {
                            int j=0,k=0;
                            path[j++]=O[i];
                            while(Op[efa].fa!=-1)
                            {
                                path[j++]=Op[efa].op;
                                efa=Op[efa].fa;
                            }
                            path[j]='\0';
                            while(Op[e].fa!=-1)
                            {
                                path1[k++]=Op[e].op;
                                e=Op[e].fa;
                            }
                            path1[k]='\0';
                            flag=true;
                            break ;
                        }
                    }
                }

            }
            if(flag) break;
            temp=Q2.front();
            Q2.pop();
            x=temp.position/3,y=temp.position%3;
            for(int i=0; i<4; i++)
            {
                int xx=x+dirx[i];
                int yy=y+diry[i];
                if(xx>=0&&xx<=2&&yy>=0&&yy<=2)
                {
                    int newp=xx*3+yy;
                    if(newp>=0&&newp<=8)
                    {
                        node temp1=temp;
                        temp1.Swap(newp,temp.position);
                        int e=code(temp1.M);
                        int efa=code(temp.M);
                        if(!vis[e])
                        {
                            vis[e]=2;
                            Op[e].fa=efa;
                            Op[e].op=inO[i];
                            Q2.push(temp1);
                        }
                        else if(vis[e]==1)
                        {
                            int j=0,k=0;
                            path1[k++]=inO[i];
                            while(Op[efa].fa!=-1)
                            {
                                path1[k++]=Op[efa].op;
                                efa=Op[efa].fa;
                            }
                            path1[k]='\0';
                            while(Op[e].fa!=-1)
                            {
                                path[j++]=Op[e].op;
                                e=Op[e].fa;
                            }
                            path[j]='\0';
                            flag=true;
                            break ;
                        }
                    }
                }
            }
            if(flag) break;
        }
        if(flag)
        {
            int len2=strlen(path);
            for(int i=len2-1; i>=0; i--)
            {
                printf("%c",path[i]);
            }
            printf("%s\n",path1);
        }
        else
        {
            printf("unsolvable\n");
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,可以得知这是一道关于迷宫问题的题目,需要使用Java语言进行编写。具体来说,这道题目需要实现一个迷宫的搜索算法,找到从起点到终点的最短路径。可以使用广度优先搜索或者深度优先搜索算法来解决这个问题。 下面是一个使用广度优先搜索算法的Java代码示例: ```java import java.util.*; public class Main { static int[][] maze = new int[5][5]; // 迷宫地图 static int[][] dir = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; // 方向数组 static boolean[][] vis = new boolean[5][5]; // 标记数组 static int[][] pre = new int[5][5]; // 记录路径 public static void main(String[] args) { Scanner sc = new Scanner(System.in); for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { maze[i][j] = sc.nextInt(); } } bfs(0, 0); Stack<Integer> stack = new Stack<>(); int x = 4, y = 4; while (x != 0 || y != 0) { stack.push(x * 5 + y); int t = pre[x][y]; x = t / 5; y = t % 5; } stack.push(0); while (!stack.empty()) { System.out.print(stack.pop() + " "); } } static void bfs(int x, int y) { Queue<Integer> qx = new LinkedList<>(); Queue<Integer> qy = new LinkedList<>(); qx.offer(x); qy.offer(y); vis[x][y] = true; while (!qx.isEmpty()) { int tx = qx.poll(); int ty = qy.poll(); if (tx == 4 && ty == 4) { return; } for (int i = 0; i < 4; i++) { int nx = tx + dir[i][0]; int ny = ty + dir[i][1]; if (nx >= 0 && nx < 5 && ny >= 0 && ny < 5 && maze[nx][ny] == 0 && !vis[nx][ny]) { vis[nx][ny] = true; pre[nx][ny] = tx * 5 + ty; qx.offer(nx); qy.offer(ny); } } } } } ``` 该代码使用了广度优先搜索算法,首先读入迷宫地图,然后从起点开始进行搜索,直到找到终点为止。在搜索的过程中,使用标记数组记录已经访问过的位置,使用路径数组记录路径。最后,使用栈来输出路径。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值