[蓝桥杯2016初赛]卡片换位

你玩过华容道的游戏吗?这是个类似的,但更简单的游戏。看下面 3 x 2 的格子
±–±--±–+
| A | * | * |
±–±--±–+
| B | | * |
±–±--±–+
在其中放5张牌,其中A代表关羽,B代表张飞,* 代表士兵。还有一个格子是空着的。
你可以把一张牌移动到相邻的空格中去(对角不算相邻)。
游戏的目标是:关羽和张飞交换位置,其它的牌随便在哪里都可以。
输入
输入存在多组测试数据,对于每组测试数据:
输入两行6个字符表示当前的局面
输出
对于每组测试数据输出一个整数表示答案:
样例输入
*A
**B
A B


样例输出
13
12
没什么好说的 见最小和最短知bfs,额bfs是队列(fifo表)dfs是栈(lifo)(其实我是不懂什么意思)
题解:
1、因为棋盘只有两行,可以把他处理成一行处理(BFS的时候方便标记这个棋盘状态),注意隔离边界(用#将第一行和第二行隔离)

2、用set集合记录走过的每一个状态,标记走过的棋盘状态

3、从空格位置开始搜索,目标状态是棋盘中A、B位置互换

#include<iostream>
#include<queue>
#include<algorithm>
#include<set>
using namespace std;
//queue 和set 都是c++ stl标准模板库里的模板。看来学会这个很有用的!

#include<iostream>
#include<queue>
#include<algorithm>
#include<set>
using namespace std;
int dir[4]={-1,1,4,-4};//左右下上
struct node
{
    int x;
    string s;//保存不同的图,同时用set去标记
    int cnt;
}A,B,K;
void bfs()
{
    queue<node>p;
    p.push(K);
    set<string>se;
    se.insert(K.s);
    while(!p.empty())
    {
        node now=p.front();
        p.pop();   
        for(int i=0;i<4;i++)
        {
            string ss=now.s;
            int tx=now.x+dir[i];
            if((tx>=0&&tx<3)||(tx>3&&tx<7))
            {
                char h=ss[now.x];
                ss[now.x]=ss[tx];
                ss[tx]=h;
                node temp;
                temp.x=tx;
                temp.s=ss;
                temp.cnt=now.cnt+1;
                if(ss[B.x]=='A'&&ss[A.x]=='B')
                {
                    cout<<temp.cnt<<endl;
                    //cout<<temp.s<<endl;
                    return ;
                }
                if(se.count(ss)==0)//避免往回走,标记棋盘状态
                {
                    se.insert(ss);
                    p.push(temp);
                }
            }
        }
    }
}
int main()
{
    string str,s1,s2;
    while(getline(cin,s1))
    {
        getline(cin,s2);
        str=s1+"#"+s2;//把二行的图转化为一行,用#分割第一行和第二行
        for(int i=0;i<7;i++)
        {
            if(str[i]=='A')
                A.x=i;
            if(str[i]=='B')
                B.x=i;
            if(str[i]==' ')
                K.x=i;
        }
        K.cnt=0;
        K.s=str;
        bfs();
    }
    
    return 0;
}
转载自:https://www.cnblogs.com/-citywall123/p/12313014.html
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值