POJ 1077 Eight(bfs+康托展开)

Eight

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 41040   Accepted: 16901   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

题目大意与分析

输入一个3x3的棋盘,每次将0上下左右移动,直到变换成为123456780的状态,求最短路线

BFS+Contor变换,康托展开公式:

以此求得的是在当前状态前面的状态数量

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <queue>
#include <string>
using namespace std;

struct node
{
    int s[9];
    string road;
    int order;
    int add0;
};
struct node start;
int jiecheng[10],f[2][4]={0,0,-1,1,-1,1,0,0},vis[400005],flag=0;
string anss;
char fang[5]="lrud";
int Contor(int s[],int n)
{
    int order=0;
    for(int i=0;i<n;i++)
    {
        int num=0;
        for(int j=i+1;j<n;j++)
        {
            if(s[j]<s[i])
            num++;
        }
        order+=num*jiecheng[n-i-1];
    }
    return order+1;
}

void bfs()
{
    queue<struct node>q;
    q.push(start);
    vis[start.order]=1;
    while(!q.empty())
    {
        struct node now=q.front();
        if(now.order==46234)
        {
            flag=1;
            anss=now.road;
            break;
        }
        q.pop();
        int x=now.add0/3;
        int y=now.add0%3;
        int i;
        for(i=0;i<4;i++)
        {
            int xx=x+f[0][i];
            int yy=y+f[1][i];
            if(xx>=0&&xx<3&&yy>=0&&yy<3)
            {
                int add1=xx*3+yy;
                struct node next=now;
                next.add0=add1;
                next.s[now.add0]=next.s[add1];
                next.s[add1]=0;
                next.add0=add1;
                next.order=Contor(next.s,9);
                if(vis[next.order]==0)
                {
                    vis[next.order]=1;
                    next.road=now.road+fang[i];
                    q.push(next);
                }
            }
        }
    }
}

int main()
{
    char x;
    for(int i=0;i<9;i++)
    {
        cin>>x;
        if(x==‘x‘)
        {
            start.s[i]=0;
            start.add0=i;
        }
        else
        start.s[i]=x-‘0‘;
    }
    start.order=Contor(start.s,9);
    jiecheng[0]=1;
    for(int i=1;i<=9;i++)
    {
        jiecheng[i]=i*jiecheng[i-1];
    }
    bfs();
    if(flag)
    cout<<anss<<endl;
    else
    cout<<"unsolvable"<<endl;
 } 

原文地址:https://www.cnblogs.com/dyhaohaoxuexi/p/12655476.html

时间: 2024-10-01 04:15:33

POJ 1077 Eight(bfs+康托展开)的相关文章

POJ 1077 Eight(康托展开+BFS)

Eight Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 30176   Accepted: 13119   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

poj 1077 八数码(BFS+康托展开)

1 /* 2 题意:八数码问题,给出3*3的矩阵含1~8以及x,给出一个符合的解使得移动后的矩阵的顺序为1~8,最后为x 3 4 题解:BFS 5 需要用到康托展开来表示状态,不然数组无法完全表示所有状态,这样BFS就无法判断找不到解的情况(status 6 的0ms,0KB究竟是怎么做到的,简直不能想象=.=) 7 */ 8 #include <cstdio> 9 #include <cstring> 10 #include <queue> 11 #include &

hdu 1430 (BFS 康托展开 或 map )

第一眼看到这题就直接BFS爆搜,第一发爆了内存,傻逼了忘标记了,然后就改,咋标记呢. 然后想到用map函数,就8!个不同的排列,换成字符串用map标记.然后又交一发果断超时,伤心,最恨超时,还不如来个wa算了. 然后卡着了,后来上网上搜了,要用康托展开,康托展开是什么鬼?然后学习了一下,就是个映射,感觉和map差不多. http://blog.csdn.net/zhongkeli/article/details/6966805这个学习一下康托展开. 其实本题的关键不是康托展开,而是置换. 以12

HDU 1043 Eight(双向BFS+康托展开)

http://acm.hdu.edu.cn/showproblem.php?pid=1043 题意:给出一个八数码,求出到达指定状态的路径. 思路:路径寻找问题.在这道题里用到的知识点挺多的.第一次用双向BFS来做. ①双向BFS 在单向BFS的基础上,多建一个从终止状态开始搜索的队列,当然这个时候需要两个vis[]辅助数组,分别记录两个队列的访问情况,当两个队列相遇时即可终止循环. ②康托展开 X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[

hdu 5012 bfs 康托展开

Dice Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 491    Accepted Submission(s): 290 Problem Description There are 2 special dices on the table. On each face of the dice, a distinct number w

【HDU - 1043】Eight(反向bfs+康托展开)

Eight Descriptions: 简单介绍一下八数码问题:在一个3×3的九宫格上,填有1~8八个数字,空余一个位置,例如下图: 1 2 3 4 5 6 7 8   在上图中,由于右下角位置是空的,你可以移动数字,比如可以将数字6下移一位: 1 2 3   1 2 3 4 5 6 → 4 5   7 8     7 8 6 或者将数字8右移一位: 1 2 3   1 2 3 4 5 6 → 4 5 6 7 8     7   8 1~8按顺序排列的情况称为"初始状态"(如最上方图)

hdu.1430.魔板(bfs + 康托展开)

魔板 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 2170    Accepted Submission(s): 455 Problem Description 在魔方风靡全球之后不久,Rubik先生发明了它的简化版——魔板.魔板由8个同样大小的方块组成,每个方块颜色均不相同,可用数字1-8分别表示.任一时刻魔板的状态可用方块的颜

BFS+康托展开(洛谷1379 八数码难题)

在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变. 输入格式: 输入初试状态,一行九个数字,空格用0表示 输出格式: 只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据) 输入样例#1: 2831

poj 1077 Eight (BFS)

八数码问题,各种解法. /* // BFS #include<iostream> #include<cstdio> #include<queue> using namespace std; // 把1..n的排列映射为数字 0..(n!-1) int fac[] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 };//... int order(const char *s, int n) { int i, j, tem