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


    题目链接:http://oj.ecustacm.cn/problem.php?id=1296

    题目描述

    你玩过华容道的游戏吗?这是个类似的,但更简单的游戏。看下面 3 x 2 的格子
        +---+---+---+
        | A | * | * | 
        +---+---+---+
        | B |   | * |
        +---+---+---+
    在其中放5张牌,其中A代表关羽,B代表张飞,* 代表士兵。还有一个格子是空着的。
    你可以把一张牌移动到相邻的空格中去(对角不算相邻)。
    游戏的目标是:关羽和张飞交换位置,其它的牌随便在哪里都可以。

    输入

    输入存在多组测试数据,对于每组测试数据:
    输入两行6个字符表示当前的局面

    输出

    对于每组测试数据输出一个整数表示答案

    样例输入 Copy

    * A
    **B
    A B
    ***

    样例输出 Copy

    17
    12

    思路:

    题目问最少需要几次,那么很容易想到利用 BFS 去求解

    但是这道题相当于一个图的遍历,隐式图的遍历要注意去重的问题,这也是这道题的一个难点。

    这里采用开一个数组 去记录 A B 空格三个的位置(因为它要求其他的无所谓),这样就可以完成去重的任务了

    然后我们每次都从空格开始走,和普通的 BFS 是一样的

    #include <iostream>
    #include <algorithm>
    #include <string>
    #include <string.h>
    #include <vector>
    #include <map>
    #include <stack>
    #include <set>
    #include <queue>
    #include <math.h>
    #include <cstdio>
    #include <iomanip>
    #include <time.h>
     
    #define LL long long
    #define INF 0x3f3f3f3f
    #define ls nod<<1
    #define rs (nod<<1)+1
     
    const int maxn = 1e5 + 10 ;
    const LL mod = 20010905;
     
    char map[10][10];
    int row_a,row_b,col_a,col_b,row,col;
    int dir[4][2] = {0,1,0,-1,1,0,-1,0};
    int vis[3][3][3][3][3][3];
     
    struct Node {
        int r,c;
        int ar,ac;
        int br,bc;
        int step;
    };
     
     
    void bfs() {
        std::queue<Node> q;
        Node now;
        now.r = row;
        now.c = col;
        now.ar = row_a,now.ac = col_a;
        now.br = row_b,now.bc = col_b;
        now.step = 0;
        q.push(now);
        while (!q.empty()) {
            now = q.front();
            q.pop();
            if (vis[now.ar][now.ac][now.br][now.bc][now.r][now.c])
                continue;
            vis[now.ar][now.ac][now.br][now.bc][now.r][now.c] = 1;
            if (now.ar == row_b && now.ac == col_b && now.br == row_a && now.bc == col_a ) {
                printf("%d
    ",now.step);
                return ;
            }
            for (int i = 0;i < 4;i++) {
                int x = now.r + dir[i][0];
                int y = now.c + dir[i][1];
                if (x < 0 || x > 1 || y < 0 || y > 2)
                    continue;
                Node ed = now;
                ed.r = x,ed.c = y;
                ed.step++;
                if (x == now.ar && y == now.ac) {
                    ed.ac = now.c;
                    ed.ar = now.r;
                }
                if (x == now.br && y == now.bc) {
                    ed.bc = now.c;
                    ed.br = now.r;
                }
                if (vis[ed.ar][ed.ac][ed.br][ed.bc][ed.r][ed.c])
                    continue;
                q.push(ed);
            }
        }
    }
     
    int main() {
        while (gets(map[0]) != NULL ) {
            gets(map[1]);
            memset(vis,0, sizeof(vis));
            for (int i = 0; i <= 1; i++) {
                for (int j = 0; j <= 2; j++) {
                    if (map[i][j] == ' ') {
                        row = i;
                        col = j;
                    }
                    if (map[i][j] == 'A') {
                        row_a = i;
                        col_a = j;
                    }
                    if (map[i][j] == 'B') {
                        row_b = i;
                        col_b = j;
                    }
                }
            }
            bfs();
        }
        return 0;
    }

    还有一种 DFS 的写法,大致的想法也是差不多的

    #include <iostream>
    #include <algorithm>
    #include <string>
    #include <string.h>
    #include <vector>
    #include <map>
    #include <stack>
    #include <set>
    #include <queue>
    #include <math.h>
    #include <cstdio>
    #include <iomanip>
    #include <time.h>
    
    using namespace std;
    #define inf 0x3f3f3f3f
    int minn=inf;
    using namespace std;
    int go[4][2]= {0,1,0,-1,1,0,-1,0};//方向向量
    int vis[3][3][3][3][3][3];//标记数组
    struct node
    {
        int x;
        int y;
    } a,b,k;//分别记录a,b和空格的坐标
    void input()//处理输入
    {
        char s;
        while((s=getchar())!=EOF){
            for(int i=0; i<2; i++)
            {
                for(int j=0; j<3; j++)
                {
                    s=getchar();
                    if(s==' ')
                    {
                        k.x=i;
                        k.y=j;
                    }
                    if(s=='A')
                    {
                        a.x=i;
                        a.y=j;
                    }
                    if(s=='B')
                    {
                        b.x=i;
                        b.y=j;
                    }
                }
                getchar();
            }
        }
    }
    void dfs(int x1,int y1,int x2,int y2,int x,int y,int step)
    {
        if(step>minn)
            return;
        if(x1==b.x&&y1==b.y&&x2==a.x&&y2==a.y)//x1y1到达b x2y2到达a 难道xy是空格?
        {
            minn=step;
            return;
        }
        //判断越界
        if(x<0||x>1||y<0||y>2)
            return;
        if(x1<0||x1>1||y1<0||y1>2)
            return;
        if(x2<0||x2>1||y2<0||y2>2)
            return;
        if(vis[x1][y1][x2][y2][x][y]==1)//三个相对位置被使用过
            return;
        vis[x1][y1][x2][y2][x][y]=1;//标记已使用
        for(int i=0; i<4; i++)
        {
            int xx=x+go[i][0];
            int yy=y+go[i][1];
            if(xx==x1&&yy==y1)//新的一步走到了A处
                dfs(x,y,x2,y2,x1,y1,step+1);//int x1,int y1,int x2,int y2,int x,int y,int step  走到A处,xy和A直接交换位置带入
            else if(xx==x2&&yy==y2)
                dfs(x1,y1,x,y,x2,y2,step+1);//走到B处,xy和B交换带入
            else
                dfs(x1,y1,x2,y2,xx,yy,step+1);//和AB无关则,空格位置改变
        }
        vis[x1][y1][x2][y2][x][y]=0;
    }
    int main()
    {
        char s;
        while((s=getchar())!=EOF) {
            if (s == ' ') {
                k.x = 0;
                k.y = 0;
            }
            if (s == 'A') {
                a.x = 0;
                a.y = 0;
            }
            if (s == 'B') {
                b.x = 0;
                b.y = 0;
            }
            for (int i = 0; i < 2; i++) {
                for (int j = 0; j < 3; j++) {
                    if (i == 0 && j == 0)
                        continue;
                    s = getchar();
                    if (s == ' ') {
                        k.x = i;
                        k.y = j;
                    }
                    if (s == 'A') {
                        a.x = i;
                        a.y = j;
                    }
                    if (s == 'B') {
                        b.x = i;
                        b.y = j;
                    }
                }
                getchar();
            }
            minn=inf;
            memset(vis,0, sizeof(vis));
            dfs(a.x, a.y, b.x, b.y, k.x, k.y, 0);
            printf("%d
    ", minn);
        }
        return 0;
    }
  • 相关阅读:
    第一次实习项目总结
    javascript整理笔记(一)-----写项目的小技巧
    Vue(项目踩坑)_These dependencies were not found: * !!vue-style-loader!css-loader?{"sourceMap":true}!../../../node_modules/vue-loader/lib/style-compiler/index?{"vue"
    JS(递归-记一次面试题)-写一个get函数,get({a:1}, 'a')输出1,get({a : {b:2}},‘a.b’)输出2,按照此规律写一个函数
    html5_音视频的兼容性写法
    canvas_画出图片的马赛克
    项目(踩坑)_移动端在使用touch滑动事件的时候会出现抖动现象
    vue+mongoose+node.js项目总结第七篇_express框架中使用socket.io插件实现在线聊天功能(前端消息发送-后端接收逻辑)
    网址
    RAII Theory && auto_ptr
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/12245117.html
Copyright © 2020-2023  润新知