机试题——黄金城寻宝

题目描述

在一个遥远的沙漠中,有一个隐藏着无数宝藏的迷宫,只有最聪明和最勇敢的人才能进入并找到出路。

但是,这个迷宫并不是那么容易通过的,它充满了各种危险和难题。除了一些隐藏在地面上的陷阱之外,还有一些时隐时现的墙壁,它们会随机地出现和消失,阻挡前进。这是一个 ( n * n ) 大小的迷宫,迷宫中存在着 ( k ) 个陷阱,并且每个位置都存在着一个墙壁的状态循环,状态循环以 3 个单位时间作为一个循环,0 表示没有墙壁,1 表示有墙壁。

在每个单位时间可以向上、下、左、右某个方向移动一个地图单位,当然也可以选择原地踏步。

限制:

  • 如果移动方向上有陷阱,或者移动目的地在下一个单位时间出现墙壁,则不可以朝该方向移动。
  • 同时,如果当前位置在下一个单位时间会出现墙壁,那也不可以选择停在原地。

我们需要计算出找到宝藏的最短时间。可能并到不了目的地哦,这种情况输出 -1。

输入描述

  • 第一行:一个整数 ( n ),表示迷宫的大小,( 2 < n <100 )。
  • 第二行:一个整数 ( k ),表示迷宫中陷阱的数量,( 0 < k < =n *n - 2 )。
  • 接下来一行:( 2 * k ) 个整数,具体为 ( row_1 col_1 row_2 col_2
    …row_k col_k ),表示位置 ( row_i, col_i ) 存在一个陷阱。
  • 接下来一行为两对整数 ( row_1, col_1) 和 ( row_2, col_2),表示宝藏的位置和起始位置。
  • 然后接下来 ( n ) 行:每行 ( n ) 个字符串空格分开,每个字符串长度固定为 3,内容固定只有 0 和 1,表示每个位置的墙壁的状态循环。

注意:地图左上角为 (0,0),输入保证所有位置合法。

输出描述

输出一个整数,表示找到宝藏的最短时间。

输入样例

3
2
1 0 1 2
2 1 2 0
100 100 100
100 000 100
000 000 001
1

最快的移动顺序:[2,0] -> [2,1]

3
2
1 0 2 0
0 1 2 2
000 000 001
010 101 101
110 010 000
5

最快的移动顺序:[2,2] -> [1,2] -> [2,2] -> [2,1] -> [1,1] -> [0,1]

解题思路

  1. 初始化迷宫
  • 读取迷宫大小 (n) 和陷阱数量 (k)。
  • 读取陷阱位置,标记在迷宫中。
  • 读取宝藏位置和塔子哥的起始位置。
  • 读取每个位置的墙壁状态循环。
  1. 动态规划与广度优先搜索 (BFS)
  • 使用三维数组 dp[i][j][t] 表示到达位置 (i, j) 且时间为 ( t%3) 的最小时间。
  • 使用队列进行广度优先搜索,从起点开始,逐步探索可达的位置。
  • 对于每个位置 (i, j) 和时间 (t),尝试向上、下、左、右移动或原地停留:
    • 如果目标位置没有陷阱且墙壁状态允许通过,则更新 dp 数组,并将新位置加入队列。
    • 如果到达宝藏位置,直接输出当前时间并结束程序。
  1. 检查是否可达
  • 如果队列为空且未到达宝藏位置,说明无法到达宝藏,输出 -1。

代码

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include 
#include 
#include 
using namespace std;
int n, k;// 迷宫大小 陷阱数量
int dx[5] = { 0,0,1,-1,0 };
int dy[5] = { 1,-1,0,0,0 };//  上下左右和不动
string g[105][105];// 地图
int no[105][105];//陷阱
int tx, ty;//宝藏
int bx, by;//开始
int dp[105][105][3];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    memset(no, 0, sizeof(no));
    cin >> n >> k;
    int x, y;
    for (int i = 0; i < k; i++) {
        cin >> x >> y;
        no[x][y] = 1;
    }
    cin >> tx >> ty;
    cin >> bx >> by;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cin >> g[i][j];
            for (int z = 0; z < 3; z++) dp[i][j][z] = 100000;
        }
    }
    // 使用dp更新距离 i j位置上时间为time%3的最小值 
    // 也就是有状态的bfs
    queue<vector<int>> q; // 当前位置和时间
    dp[bx][by][0] = 0;
    q.push({ bx,by,0 });
    while (!q.empty()) {
        vector<int> cur = q.front();
        q.pop();
        int cx = cur[0];
        int cy = cur[1];
        int ct = cur[2];
        if (cx == tx && cy == ty) {
            cout << ct;
            return 0;
        }
        for (int i = 0; i < 5; i++) {
            int nx = cx + dx[i];
            int ny = cy + dy[i];
            int nt = ct + 1;
            // 有障碍物
            if (nx<0||nx>=n||ny<0||ny>=n||no[nx][ny]||g[nx][ny][nt%3] == '1') continue;
            if (dp[nx][ny][nt % 3] > nt) {
                // 出现更小的 可以更新路径
                dp[nx][ny][nt % 3] = nt;
                q.push({ nx,ny,nt });
            }
        }
    }
    cout << -1;
}

你可能感兴趣的:(#,hw机试题,算法,c++,图论)