HDU 3567 Eight II

题目链接
太太太棒了,又又又学到了许多
在这里插入图片描述
Problem Description

Eight-puzzle, which is also called “Nine grids”, comes from an old game.

In this game, you are given a 3 by 3 board and 8 tiles. The tiles are numbered from 1 to 8 and each covers a grid. As you see, there is a blank grid which can be represented as an ‘X’. Tiles in grids having a common edge with the blank grid can be moved into that blank grid. This operation leads to an exchange of ‘X’ with one tile.

We use the symbol ‘r’ to represent exchanging ‘X’ with the tile on its right side, and ‘l’ for the left side, ‘u’ for the one above it, ‘d’ for the one below it.

A state of the board can be represented by a string S using the rule showed below.

The problem is to operate an operation list of ‘r’, ‘u’, ‘l’, ‘d’ to turn the state of the board from state A to state B. You are required to find the result which meets the following constrains:

  1. It is of minimum length among all possible solutions.
  2. It is the lexicographically smallest one of all solutions of minimum length.

Input

The first line is T (T <= 200), which means the number of test cases of this problem.

The input of each test case consists of two lines with state A occupying the first line and state B on the second line.
It is guaranteed that there is an available solution from state A to B.

Output

For each test case two lines are expected.

The first line is in the format of “Case x: d”, in which x is the case number counted from one, d is the minimum length of operation list you need to turn A to B.
S is the operation list meeting the constraints and it should be showed on the second line.

Sample Input

2
12X453786
12345678X
564178X23
7568X4123

Sample Output

Case 1: 2
dd
Case 2: 8
urrulldr

大致题意
其实和第一题一样,只不过这次的结果是不固定的

具体思路
题目一中不是以结尾是12345678X化作0作为广搜起点吗,一开始把结尾换做数字200组数据自己跑,T了。。。(正常,淡定),后面看博客时候发现了二次映射,除X之外的所有制按照顺序映射

123X65487-->123045678
1-->1	2-->2	3-->3	
x-->0	6-->4	5-->5	
4-->6	8-->7	7-->8

这样一来其实不难发现,结果只有以下九种

"012345678","102345678","120345678",
"123045678","123405678","123450678",
"123456078","123456708","123456780"

那么一来,只要把这九种结果bfs预处理以下就可以了,手法和第一题一样
在这里有个需要注意的,输出步数最少,且按照字典序最小输出,这便要求我们bfs的时候按照字典序先后for循环了,但这么一来,第一题原本是广搜上一步,在这里需要广搜下一步

120		123 	我们不难看出当以结果bfs下一步 123		123		120
453	-->	456								    456	-->	450 --> 453
786		780									780		786     786

在这里我们输出的是uu与原有的标准答案相反,因为是以结果下一步bfs,每一步记录上一步
接下来我们看个神奇的东西(开始bfs走

123		120 	我们不难看出当以开始bfs下一步 120 	123		123
456	-->	453								    453		450 --> 456
780		786									786	 	786     780

此时输出就是dd,我们可以根据结果bfs到起点,步骤相反转换为,起点到重点方向相同
在这里也许有人会问,本来不就是起点到终点吗,但是起点是随机的,只有结果是固定的九种,所以只能以终点bfs,题目又要求字典序,所以只能以正向步骤,一旦结果转换,未必满足字典序(WA了好几发发现的)在这里我们就需要去以开始作为终点,这里因为起点是随机的,我们需要将其映射为九种的情况,最后从终点回溯回去,因为回溯是从后往前,于是用了个栈来使得结果正过来

#include<bits/stdc++.h>
using namespace std;
int factorial[10]= {1,1,2,6,24,120,720,5040,40320};
char endresult[15][10] = {"012345678","102345678","120345678",
                          "123045678","123405678","123450678",
                          "123456078","123456708","123456780"
                         };
int change[4][2]={{1,0},{0,-1},{0,1},{-1,0}};
char dic[10]={'d','l','r','u'};
int flags[400000];
char mapping[10];
struct Node
{
    int s,xy;
    Node() {}
    Node(int S,int XY)
    {
        s=S,xy=XY;
    }
};
struct Path
{
    int from,opt;
} p[10][400000];
int getnum(int v)
{
    int sum=0;
    for (int i=0; i<=8; i++)
    {
        for (int j=i+1; j<=8; j++)
        {
            if (endresult[v][i]-'0'>endresult[v][j]-'0')
            {
                sum=sum+factorial[8-i];
            }
        }
    }
    return sum;
}
void Swap(int x,int y)
{
    char d;
    d=endresult[9][x];
    endresult[9][x]=endresult[9][y];
    endresult[9][y]=d;
}
void getstr(int v)
{
    int tmp[10],flag[10];
    memset(flag,0,sizeof(flag));
    for (int i=0; i<=8; i++)
    {
        tmp[i]=v/factorial[8-i];
        v=v%factorial[8-i];
    }
    for (int i=0; i<=8; i++)
    {
        int num=0;
        for (int j=0; j<=8; j++)
        {
            if (flag[j]==0)
            {
                num++;
            }
            if (num==tmp[i]+1)
            {
                endresult[9][i]=j+1+'0';
                flag[j]=1;
                break;
            }
        }
    }
}
void bfs(int S,int XY,int V)
{
    memset(flags,0,sizeof(flags));
    queue<Node>dui;
    dui.push(Node(S,XY));
    flags[S]=1;
    p[V][S].from=-1;
    p[V][S].opt=-1;
    while (!dui.empty())
    {
        Node now=dui.front();
        dui.pop();
        int x=now.xy/3;
        int y=now.xy%3;
        getstr(now.s);
        for (int i=0; i<4; i++)
        {
            int xx=x+change[i][0];
            int yy=y+change[i][1];
            if (!(xx>=0&&yy>=0&&xx<3&&yy<3))
            {
                continue;
            }
            int newxy=3*xx+yy;
            Swap(newxy,now.xy);
            int newnum=getnum(9);
            if (flags[newnum]==1)
            {
                Swap(newxy,now.xy);
                continue;
            }
            p[V][newnum].from=now.s;
            p[V][newnum].opt=i;
            flags[newnum]=1;
            dui.push(Node(newnum,newxy));
            Swap(newxy,now.xy);
        }
    }
}
void resultsstart()
{
    for (int i=0; i<9; i++)
    {
        int num=getnum(i);
        bfs(num,i,i);
    }
}
int main()
{
    resultsstart();
    int t;
    scanf("%d%*c",&t);
    for (int i=1; i<=t; i++)
    {
        int v;
        scanf("%s%*c",endresult[10]);
        scanf("%s%*c",endresult[11]);
        int num=1;
        for (int j=0; j<9; j++)
        {
            if (endresult[10][j]=='X')
            {
                v=j;
                endresult[10][j]='0';
            }
            else
            {
                mapping[endresult[10][j]-'0']='0'+num;
                endresult[10][j]='0'+num;
                num++;
            }
        }
        for (int j=0; j<9; j++)
        {
            if (endresult[11][j]=='X')
            {
                endresult[11][j]='0';
            }
            else
            {
                endresult[11][j]=mapping[endresult[11][j]-'0'];
            }
        }
        int arrange=getnum(11);
        int ansnum=0;
        stack<char>zhanans;
        while (1)
        {
            if (p[v][arrange].from==-1)
            {
                break;
            }
            zhanans.push(dic[p[v][arrange].opt]);
            arrange=p[v][arrange].from;
            ansnum++;
        }
        printf("Case %d: %d\n",i,ansnum);
        while (!zhanans.empty())
        {
            char ansc=zhanans.top();
            zhanans.pop();
            printf("%c",ansc);
        }
        printf("\n");
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值