HDU 1043(康拓展开+BFS+八数码问题)

题意:给定一个现有的九宫格布局,请输出将它移动至初始状态的移动方法的步骤。

思路:自己没什么思路。学了康拓展开,看了别人的博客才理解了,暂且先放着别人的代码,,等自己实力足够了再自己写试试

//HDU1043-经典BFS-八数码
//多组数据-需要计算全部路径后直接输出(POJ1077数据较弱)
//反向搜索+打表(离线)
//Time:109Ms    Memory:25412K

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

#define MAX 400000
#define AIM 46234    //123456780对应的康托Hash值

bool v[MAX];
char path[MAX][40];    //总路径
int len;    //路径长

/*udlr*/
char *dir = "durl";    //反向搜索
int mov[4][2] = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };

//八数码状态结构体
struct Node{
    int s[9];
    int loc;    //空位
    int status;    //Hash值-排列值
    int fa;    //记录父状态
    char d;    //到此状态的移动方向
}n[MAX];

int fac[10] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 };
//康托逆展开-返回Hash值
int Inverse_cantor(int s[9])
{
    int sum = 0;
    for (int i = 0; i < 9; i++)
    {
        int num = 0;    //逆序数计数器
        for (int j = i + 1; j < 9; j++)
            if (s[j] < s[i])
                num++;
        sum += num*fac[9 - i - 1];
    }
    return sum + 1;
}

/*反向记录路径*/
void count_path(Node end)
{
    int status = end.status;
    int f = end.fa;
    len = 0;
    path[status][len++] = end.d;
    while (f)
    {
        path[status][len++] = n[f].d;//方向记录
        f = n[f].fa;    //查找父结点
    }
}

void BFS()
{
    memset(v, 0, sizeof(v));
    Node next;    //下一临时状态
    int head = 0, tail = 0;
    /*目标状态*/
    for (int i = 0; i < 8; i++)
        n[0].s[i] = i + 1;
    n[0].s[8] = 0;
    n[0].loc = 8;
    n[0].status = AIM;
    v[AIM] = true;
    while (head <= tail)    //模拟队列
    {
        //计算二维坐标
        int x = n[head].loc / 3;
        int y = n[head].loc % 3;
        for (int i = 0; i < 4; i++)    //遍历四方向
        {
            int tx = x + mov[i][0];
            int ty = y + mov[i][1];
            if (tx < 0 || tx>2 || ty < 0 || ty>2)continue;
            //新状态更新
            next = n[head];
            next.loc = tx * 3 + ty;    //计算新空位
            next.s[n[head].loc] = next.s[next.loc];    //原空位替换
            next.s[next.loc] = 0;    //新空位
            next.fa = head;
            next.d = dir[i];
            next.status = Inverse_cantor(next.s);
            //判重并入队
            if (!v[next.status])
            {
                v[next.status] = true;
                count_path(next);
                n[++tail] = next;
            }
        }
        head++;
    }
}

int main()
{
    /* BFS-打表 */
    BFS();
    /*input*/
    char ch[3];
    Node cur;
    while (scanf("%s", ch) != EOF)
    {
        if (!strcmp(ch, "x"))
            cur.s[0] = 0, cur.loc = 0;
        else cur.s[0] = ch[0] - '0';
        for (int i = 1; i < 9; i++)
        {
            scanf("%s", ch);
            if (!strcmp(ch, "x"))
                cur.s[i] = 0, cur.loc = i;
            else cur.s[i] = ch[0] - '0';
        }
        cur.status = Inverse_cantor(cur.s);
        
        /*output*/
        if (v[cur.status])
            printf("%s\n", path[cur.status]);
        else
            printf("unsolvable\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Dilly__dally/article/details/82718858