7-10 模拟炸弹人题解

《炸弹人》是HUDSON出品的一款ACT类型游戏,经典的第一作登陆在FC版本,游戏于1983年发行。游戏具体操作是一个机器人放置炸弹来炸死敌人,但也可以炸死自己,还有些增强威力与技能道具增加了游戏的可玩性。
    接下来我们就对《炸弹人》进行一次简化模拟:
首先我们需要一个 N×M 大小的矩阵来存放地图,矩阵中 '*' 代表没有点燃的炸弹,‘0’代表空地,玩家可以自定义炸弹的威力为 p (由于我们是简化模拟,所以 p 只会取 1 或者 2 );像《炸弹人》一样,炸弹可以引发自己上、下、左、右(斜角不算)各 p 格范围内产生爆炸,并且爆炸可以产生连锁反应,问至少需要进行几次引爆才可以让所有的炸弹都爆炸。

例如:
在 5×7 的矩阵

1.png

中,当玩家把炸弹的威力 p 设为 1 时至少需要进行 4 次引爆,

而当玩家把炸弹的威力 p 设为 2 时至少需要进行 3 次引爆。

输入格式:

在第一行定义矩阵的大小 n,m,1≤n,m≤103 和炸弹的威力 p,p∈{1,2},数字之间用空格隔开

随后 n 行是由‘0’和‘*’两种字符组成的 n×m 矩阵,字符之间用空格隔开。

输出格式:

在一行中输出至少需要进行几次引爆可以让所有的炸弹都爆炸。

输入样例1:

5 7 1
0 0 * * 0 0 0
0 0 * 0 0 0 0
0 0 0 0 0 * 0
0 * * 0 0 0 0
0 0 0 * 0 0 0

输出样例1:

4

输入样例2:

5 7 2
0 0 * * 0 0 0
0 0 * 0 0 0 0
0 0 0 0 0 * 0
0 * * 0 0 0 0
0 0 0 * 0 0 0

输出样例2:

3

模拟炸弹人游戏:最少引爆次数计算

问题描述

我们需要模拟经典游戏《炸弹人》中的炸弹引爆过程。给定一个N×M大小的矩阵,其中包含未引爆的炸弹('*')和空地('0')。炸弹的威力p可以是1或2,表示炸弹可以引爆上下左右p格范围内的其他炸弹。爆炸可以产生连锁反应,要求计算最少需要主动引爆多少次才能让所有炸弹爆炸。

解题思路

关键点分析

  1. ​炸弹威力影响范围​​:p=1时影响相邻4格,p=2时影响相邻8格(上下左右各2格)
  2. ​连锁反应​​:一个炸弹被引爆后会自动引爆其威力范围内的其他炸弹
  3. ​最少引爆次数​​:需要找到最少的引爆点,使得通过这些点的连锁反应能引爆所有炸弹

算法选择

  • ​广度优先搜索(BFS)​​:适合模拟爆炸的连锁反应过程
  • ​连通区域划分​​:将炸弹矩阵划分为若干个连通区域,每个区域只需引爆一次

代码实现与分析

#include<bits/stdc++.h>
using namespace std;

char grid[10005][10005];  // 存储地图
int visited[10005][10005]; // 访问标记数组
int n, m, p;               // 地图大小和炸弹威力

// p=1时的方向数组(上下左右各1格)
int dir1[4][2] = {{1,0}, {-1,0}, {0,1}, {0,-1}};

// p=2时的方向数组(上下左右各2格)
int dir2[8][2] = {{1,0}, {-1,0}, {0,1}, {0,-1}, 
                  {2,0}, {-2,0}, {0,2}, {0,-2}};

// p=1时的BFS引爆过程
void bfs1(int x, int y) {
    queue<pair<int, int>> q;
    q.push({x, y});
    grid[x][y] = '0';      // 标记为已引爆
    visited[x][y] = 1;     // 标记为已访问

    while (!q.empty()) {
        auto current = q.front();
        q.pop();
        int x0 = current.first;
        int y0 = current.second;

        // 检查四个方向
        for (int i = 0; i < 4; i++) {
            int x1 = x0 + dir1[i][0];
            int y1 = y0 + dir1[i][1];
            
            // 检查边界和是否未访问
            if (x1 > 0 && x1 <= n && y1 > 0 && y1 <= m) {
                if (grid[x1][y1] == '*' && !visited[x1][y1]) {
                    grid[x1][y1] = '0';    // 引爆该炸弹
                    visited[x1][y1] = 1;   // 标记为已访问
                    q.push({x1, y1});      // 加入队列继续传播
                }
            }
        }
    }
}

// p=2时的BFS引爆过程
void bfs2(int x, int y) {
    queue<pair<int, int>> q;
    q.push({x, y});
    grid[x][y] = '0';      // 标记为已引爆
    visited[x][y] = 1;     // 标记为已访问

    while (!q.empty()) {
        auto current = q.front();
        q.pop();
        int x0 = current.first;
        int y0 = current.second;

        // 检查八个方向
        for (int i = 0; i < 8; i++) {
            int x1 = x0 + dir2[i][0];
            int y1 = y0 + dir2[i][1];
            
            // 检查边界和是否未访问
            if (x1 > 0 && x1 <= n && y1 > 0 && y1 <= m) {
                if (grid[x1][y1] == '*' && !visited[x1][y1]) {
                    grid[x1][y1] = '0';    // 引爆该炸弹
                    visited[x1][y1] = 1;   // 标记为已访问
                    q.push({x1, y1});      // 加入队列继续传播
                }
            }
        }
    }
}

int main() {
    cin >> n >> m >> p;
    int count = 0;  // 记录最少引爆次数

    // 读取地图数据
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cin >> grid[i][j];
            visited[i][j] = 0;  // 初始化访问标记
        }
    }

    // 根据威力选择不同的引爆策略
    if (p == 1) {
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (grid[i][j] == '*') {
                    bfs1(i, j);  // 引爆并传播
                    count++;     // 增加引爆计数
                }
            }
        }
    } 
    else if (p == 2) {
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (grid[i][j] == '*') {
                    bfs2(i, j);  // 引爆并传播
                    count++;     // 增加引爆计数
                }
            }
        }
    }

    cout << count << endl;
    return 0;
}

代码解析

  1. ​数据结构​​:

    • grid数组存储地图信息
    • visited数组记录炸弹是否已被引爆
    • 方向数组dir1dir2分别对应p=1和p=2时的爆炸范围
  2. ​BFS函数​​:

    • bfs1()处理p=1的情况,引爆上下左右相邻1格的炸弹
    • bfs2()处理p=2的情况,引爆上下左右相邻2格的炸弹
    • 两种BFS都会通过队列实现连锁反应的模拟
  3. ​主函数​​:

    • 读取输入数据并初始化
    • 根据p值选择不同的引爆策略
    • 遍历地图,对每个未引爆的炸弹执行BFS并计数

复杂度分析

  • ​时间复杂度​​:O(n×m),需要遍历整个矩阵
  • ​空间复杂度​​:O(n×m),用于存储地图和访问标记

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值