[kuangbin]专题二 搜索进阶 Gap HDU - 1067【BFS】【哈希】

【题目描述】
Let’s play a card game called Gap.
You have 28 cards labeled with two-digit numbers.The first digit (from 1 to 4) represents the suit of the card,and the second digit (from 1 to 7) represents the value of the card.
First,you shu2e the cards and lay them face up on the table in four rows of seven cards,leaving a space of one card at the extreme left of each row.The following shows an example of initial layout.
让我们玩一个叫做Gap的纸牌游戏。你有28张标有两位数字的卡片。第一个数字(从1到4)代表卡的套装,第二个数字(从1到7)表示卡的值。首先,你打开卡片,把它们朝上放在桌子上,分成四排七张牌,在每行的最左边留出一张牌的空间。下面显示了初始布局的示例。
在这里插入图片描述
Next,you remove all cards of value 1,and put them in the open space at the left end of the rows:“11” to the top row,“21” to the next, and so on.
Now you have 28 cards and four spaces, called gaps, in four rows and eight columns. You start moving cards from this layout.
接下来,删除所有值为1的卡片,并将它们放在行左侧的开放空间中:“11”放在最上面的行,“21”放到下一行,以此类推。现在你有28张卡片和四个空格,叫做间隙,在四行八列中。从这个布局开始移动卡片。
在这里插入图片描述
At each move,you choose one of the four gaps and fill it with the successor of the left neighbor of the gap.The successor of a card is the next card in the same suit, when it exists.For instance the successor of “42” is “43”,and “27” has no successor.
每次移动,你可以从这四个空白中选择一个,然后用空白的左邻右舍的继任者来填充它。当一张牌存在时,它的后继人就是下一张在同一套西装里的牌。例如,“42”的继承者是“43”,而“27”则没有继任者。
In the above layout,you can move “43” to the gap at the right of “42”,or “36” to the gap at the right of “35”.If you move “43”,a new gap is generated to the right of “16”.You cannot move any card to the right of a card of value 7,nor to the right of a gap.
在上面的布局中,您可以将“43”移动到右边的“42”,或者“36”移动到右边的“35”。如果你移动“43”,一个新的差距产生在右边的“16”。你不能把任何一张牌移到价值7的牌的右边,也不能移到间隙的右边。
The goal of the game is,by choosing clever moves, to make four ascending sequences of the same suit,as follows.
该游戏的目标是,通过选择聪明的动作,使四个提升序列的同一套,如下所示。
在这里插入图片描述
Your task is to find the minimum number of moves to reach the goal layout.
您的任务是找到达到目标布局的最小移动次数。

【输入】
The input starts with a line containing the number of initial layouts that follow.
Each layout consists of five lines - a blank line and four lines which represent initial layouts of four rows. Each row has seven two-digit numbers which correspond to the cards.
输入以一行开始,其中包含后面的初始布局数。每个布局由五行组成-一条空行和四行代表四行的初始布局。每行有七个两位数的数字,它们对应于卡片。

【输出】
For each initial layout, produce a line with the minimum number of moves to reach the goal layout. Note that this number should not include the initial four moves of the cards of value 1. If there is no move sequence from the initial layout to the goal layout, produce “-1”.
对于每个初始布局,生成一条具有最小移动次数的行以达到目标布局。请注意,这个数字不应该包括值1的卡片的最初四个移动。如果没有从初始布局到目标布局的移动序列,则生成“-1”。

【样例输入】
4

12 13 14 15 16 17 21
22 23 24 25 26 27 31
32 33 34 35 36 37 41
42 43 44 45 46 47 11

26 31 13 44 21 24 42
17 45 23 25 41 36 11
46 34 14 12 37 32 47
16 43 27 35 22 33 15

17 12 16 13 15 14 11
27 22 26 23 25 24 21
37 32 36 33 35 34 31
47 42 46 43 45 44 41

27 14 22 35 32 46 33
13 17 36 24 44 21 15
43 16 45 47 23 11 26
25 37 41 34 42 12 31

【样例输出】
0
33
60
-1

题目链接:https://cn.vjudge.net/problem/HDU-1067

BFS+哈希,用map存矩阵就行

代码如下:

#include <iostream>
#include <cstring>
#include <string>
#include <queue>
#include <unordered_map>
using namespace std;
int T;
static const string st={0,11,12,13,14,15,16,17,0,
                            21,22,23,24,25,26,27,0,
                            31,32,33,34,35,36,37,0,
                            41,42,43,44,45,46,47,0};
struct Node{
    string mp;
    int step;
    int spacex[4];
    int spacey[4];
};
int mp[32];
void bfs(Node node)
{
    queue<Node> Q;
    unordered_map<string,int> m;
    memset(mp,0,sizeof(mp));
    m[st]=2;
    Q.push(node);
    if(m[node.mp])
    {
        cout<<0<<endl;
        return;
    }
    else
        m[node.mp]=1;
    while(!Q.empty())
    {
        Node now=Q.front();
        Q.pop();
        for(int k=0;k<4;k++)
        {
            Node next=now;
            bool flag=false;
            for(int i=0;i<4;i++)
            {
                for(int j=1;j<=8;j++)
                    if(next.mp[i*8+j]==next.mp[next.spacex[k]*8+next.spacey[k]-1]+1)
                    {
                        next.mp[next.spacex[k]*8+next.spacey[k]]=next.mp[i*8+j];
                        next.mp[i*8+j]=0;
                        next.spacex[k]=i;
                        next.spacey[k]=j;
                        flag=true;
                        next.step+=1;
                        break;
                    }
                if(flag)
                    break;
            }
            if(m[next.mp])
            {
                if(m[next.mp]==2)
                {
                    cout<<next.step<<endl;
                    return;
                }
                else
                    continue;
            }
            m[next.mp]=1;
            Q.push(next);
        }
    }
    cout<<-1<<endl;
}
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0),cout.tie(0);
    int T;
    cin>>T;
    while(T--)
    {
        for(int i=0;i<4;i++)
        {
            mp[i*8+1]=0;
            for(int j=2;j<=8;j++)
                cin>>mp[i*8+j];
        }
        Node pre;
        for(int i=0;i<=32;i++)
            pre.mp+='0';
        for(int i=0;i<4;i++)
            for(int j=2;j<=8;j++)
            {
                if(mp[i*8+j]==11)
                {
                    pre.mp[1]=11;
                    pre.mp[i*8+j]=0;
                    pre.spacex[0]=i;
                    pre.spacey[0]=j;
                }
                else if(mp[i*8+j]==21)
                {
                    pre.mp[9]=21;
                    pre.mp[i*8+j]=0;
                    pre.spacex[1]=i;
                    pre.spacey[1]=j;
                }
                else if(mp[i*8+j]==31)
                {
                    pre.mp[17]=31;
                    pre.mp[i*8+j]=0;
                    pre.spacex[2]=i;
                    pre.spacey[2]=j;
                }
                else if(mp[i*8+j]==41)
                {
                    pre.mp[25]=41;
                    pre.mp[i*8+j]=0;
                    pre.spacex[3]=i;
                    pre.spacey[3]=j;
                }
                else
                    pre.mp[i*8+j]=mp[i*8+j];
            }
        pre.mp[0]=0;
        pre.step=0;
        bfs(pre);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值