上海计算机学会第五届上海市青少年算法竞赛T6位置互换

位置互换

内存限制: 256 Mb时间限制: 1000 ms

题目描述

迷宫游戏是在一张 n×m的网格图中进行的,其中 a(i,j)​ 表示第 i 行、第 j 列网格的状态,每个网格有以下 4 种情况:

  • 若a(i,j)​为. ,则表示该位置为可以走的空地
  • 若a(i,j)​为# ,则表示该位置为不可走的墙壁
  • 若a(i,j)​为1 ,则表示该位置为小爱初始的位置
  • 若a(i,j)​为2 ,则表示该位置为小艾初始的位置

每一轮游戏开始时,可以自由决定是小爱先移动还是小艾先移动,他们可以移动至相邻的上下左右四个空格或原地不动,但又不可以移动至对方所在的网格中。

请问,游戏最少进行多少轮,才能使小爱和小艾互换位置?

输入格式

输入第一行,两个正整数分别表示 n,m
接下来的第 2 行至第 n+1 行,每行 m 个字符,其中第 i+1 行、第 j 列的字符表示初始时网格 a(i,j)​ 的状态。

输出格式

输出共一行,一个整数表示两人互换位置最少需要的轮数,若无法完成,则输出 No Solution

数据范围
  • 对于 50%的数据,1≤n,m≤5
  • 对于 100%的数据,1≤n,m≤30
样例数据

 输入:
3 3
1..
...
..2
输出:
4
说明:
1..       .1.       ..1       ...       2..
...  -->  ...  -->  ...  -->  2.1  -->  ...
..2       .2.       2..       ...       ..1
输入:
3 3
1..
###
..2
输出:
No Solution
说明:
被第二行的墙挡住了
输入:
2 3
1.2
#.#
输出:
4
说明:
1.2       .12       .2.       21.        2.1
#.#  -->  #.#  -->  #1#  -->  #.#   -->  #.#  
输入:
3 3
1.#
#.#
#.2
输出:
No Solution

 解析:感谢杰哥提供的解题思路及代码(gzh 跟杰哥玩编程)

BFS
加了限制的宽搜,样例把一些极端情况都给出了,所以要想办法突破限制。
以下问题要解决:

  • 从样例3可知,走过的还能走,如何解决?

  • 从样例3可知,可以一个走,一个不走,如何解决?

  • 从样例4可知,独木桥无法通过,如何解决?

  • 如何解决一个人提前到了,另一个人还要走的问题?

如果分别用一个二维数组记录两人走过的位置,基本走远了,很难解决走过还能再走的问题。
问题1:两个人走过的位置需要两个坐标,如果用维数组记录走过的位置,则哪怕走过了,只要坐标的组合没出现过,还能往回走
问题2:这个问题发生在两人都走向同一个格子的时候,那么特判处理一下,让一个走,一个不走,记录状态即可,需要注意一个走,一个不走有两种情况,都要处理。
问题3:独木桥走法唯一,只要判断两个坐标是否发生了交换这种情况,如果发生交换,则不处理,那么没有数据入队,程序提前结束,输出无法完成的信息即可。
问题4:计算出新位置的时候,特判一下是否已经到达目标位置,如果到达了,则修改为目标坐标,这样实现了一个人到了终点,另一个还能继续前进。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 40;

struct node{
    pair<int,int> a,b;
    int step;
};

int n,m;
char mp[maxn][maxn];
bool vis[maxn][maxn][maxn][maxn];
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
pair<int,int> a_start,b_start;
bool check(int x, int y)
{
    return x > 0 && x <= n && y > 0 && y <= m && mp[x][y]!='#';
}

int bfs(pair<int,int> a_start, pair<int,int> b_start)
{
    queue<node> q;
    q.push({a_start,b_start,0});
    vis[a_start.first][a_start.second][b_start.first][b_start.second]=1;
    while(q.size()){
        pair<int,int> a = q.front().a;
        pair<int,int> b = q.front().b;
        int steps = q.front().step;
        q.pop();
        if(a == b_start && b == a_start){ //目标状态
            return steps;
        }
        for(int i = 0; i < 4; i++){ //枚举所有的方向组合
            for(int j = 0; j < 4; j++){
                int na_x = a.first + dx[i],na_y = a.second + dy[i];
                int nb_x = b.first + dx[j],nb_y = b.second + dy[j];
                if (a == b_start) na_x = b_start.first,na_y = b_start.second;  //已到终点,保持不动
                if (b == a_start) nb_x = a_start.first,nb_y = a_start.second;  //已到终点,保持不动
                if(na_x==b.first && na_y == b.second && nb_x==a.first && nb_y==a.second) continue; //发生交换,规则不允许
                if (check(na_x, na_y) && check(nb_x,nb_y)){
                    if(na_x == nb_x && na_y == nb_y){  //两人移到同一个格子的情况
                        if(!vis[na_x][na_y][b.first][b.second]){  //a不动
                            vis[na_x][na_y][b.first][b.second] = 1;
                            q.push({{na_x, na_y}, {b.first, b.second}, steps + 1});
                        }
                        if(!vis[a.first][a.second][nb_x][nb_y]){  //b不动
                            vis[a.first][a.second][nb_x][nb_y] = 1;
                            q.push({{a.first, a.second}, {nb_x, nb_y}, steps + 1});
                        }
                        continue; 
                    }
                    if (!vis[na_x][na_y][nb_x][nb_y]) { //普通情况
                        vis[na_x][na_y][nb_x][nb_y] = 1;
                        q.push({{na_x, na_y}, {nb_x, nb_y}, steps + 1});
                    }
                }
   }
        } 
    }
    return -1; 
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>m;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++){
            cin>>mp[i][j];
            if(mp[i][j]=='1') a_start={i,j};
            if(mp[i][j]=='2') b_start={i,j};
      }
    int res = bfs(a_start,b_start);
    if(res == -1) cout<<"No Solution"<<"\n";
    else cout<<res<<"\n";
    return 0;
}

 

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-13 10:50:01       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-13 10:50:01       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-13 10:50:01       87 阅读
  4. Python语言-面向对象

    2024-04-13 10:50:01       96 阅读

热门阅读

  1. 为什么tcp需要四次挥手?

    2024-04-13 10:50:01       36 阅读
  2. 算法-质数 约数

    2024-04-13 10:50:01       37 阅读
  3. Docker入门

    2024-04-13 10:50:01       40 阅读
  4. 设计模式-单例模式

    2024-04-13 10:50:01       31 阅读
  5. 第十二章-Broker-同步刷盘(一)

    2024-04-13 10:50:01       33 阅读
  6. Redis相关

    2024-04-13 10:50:01       39 阅读
  7. VS2012编译Lua5.1的luafilesystem(lfs)

    2024-04-13 10:50:01       35 阅读
  8. Redis的过期策略与内存淘汰机制原理及实践

    2024-04-13 10:50:01       39 阅读
  9. 网格布局 grid

    2024-04-13 10:50:01       33 阅读
  10. CMake简单笔记

    2024-04-13 10:50:01       37 阅读
  11. (第四章)管理数组和字符串

    2024-04-13 10:50:01       39 阅读