蓝桥杯-2016CC-卡片换位

卡片换位

你玩过华容道的游戏吗?
这是个类似的,但更简单的游戏。
看下面 3 x 2 的格子

在其中放5张牌,其中A代表关羽,B代表张飞,* 代表士兵。
还有一个格子是空着的。

你可以把一张牌移动到相邻的空格中去(对角不算相邻)。
游戏的目标是:关羽和张飞交换位置,其它的牌随便在哪里都可以。

输入格式:
输入两行6个字符表示当前的局面

输出格式:
一个整数,表示最少多少步,才能把AB换位(其它牌位置随意)

例如,输入:
* A
**B

程序应该输出:
17

再例如,输入:
A B
***

程序应该输出:
12


资源约定:
峰值内存消耗 < 256M
CPU消耗 < 1000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。

注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。

提交时,注意选择所期望的编译器类型。

 

思路:用pair<int, int> 来描述一个坐标,对于每个局面都只记录A,B,空格的坐标,剩下三个*不关注他们在哪,不用记录。对于每个状态转移,视为空格在移动。然后BFS。用set记录已出现过的局面;

  • 广度优先搜索
    #include "bits/stdc++.h"
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> PII;
    struct node {
        // a表示A, b表示B, c表示空格 
        PII a, b, c;
        // 因为set要实现小于号所以这里随便敲个小于号。只要能实现排序就行 
        friend bool operator < (node n, node m) {
            if (n.a != m.a) {
                return n.a < m.a;
            } else if (n.b != m.b) {
                return n.b < m. b;
            } else {
                return n.c < m.c;
            }
        }
    } n; 
    PII A, B;
    char mp[2][4];
    // 这里的pair表示当前局面和步数 
    queue<pair<node, int> > q;
    // 记录出现过的局面 
    set<node> st;
    void check(PII c, int step) {
        // 越界情况 
        if (c.first < 0 || c.first > 1 || c.second < 0 || c.second > 2) {
            return;
        }
        node m;
        m.c = c;
        m.a = (n.a == c) ? n.c : n.a;
        m.b = (n.b == c) ? n.c : n.b;
        // 新局面之前出现过 
        if (st.count(m)) {
            return;
        }
        st.insert(m);
        q.push({m, step + 1}); 
    }
    void BFS() {
        while (!q.empty()) {
            n = q.front().first;
            int step = q.front().second;
            q.pop();
            // 已到达目标状态 
            if (n.a == B && n.b == A) {
                printf("%d\n", step);
                return;
            }
            check({n.c.first - 1, n.c.second}, step);
            check({n.c.first, n.c.second - 1}, step); 
            check({n.c.first + 1, n.c.second}, step);
            check({n.c.first, n.c.second + 1}, step);
        }
    }
    int main() {
        gets(mp[0]);
        gets(mp[1]);
        // 找到原图里A, B, 空格的位置 
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 4; j ++) {
                if (mp[i][j] == ' ') {
                    n.c = {i, j};
                }
                if (mp[i][j] == 'A') {
                    n.a = A = {i, j};
                }
                if (mp[i][j] == 'B') {
                    n.b = B = {i, j};
                }
            }
        }
        q.push({n, 0});
        st.insert(n); 
        BFS();
        return 0;
    }

    这题如果会BFS还是很好想的,但是check那里想了好久。check写的好会使代码比较整洁不易错。但是没有OJ可以提交这题,所以如果代码有问题请指出。

posted @ 2019-03-14 15:59  Jathon-cnblogs  阅读(661)  评论(0编辑  收藏  举报