top1编程
← 返回题目
题解

安放地雷2

1 条题解

  • 0
    @ 2026-8-5 23:59:33

    P4704 安放地雷2(入门)

    解题思路

    第一步:看懂题目。 一个 n×n 的格子地图,格子里有三种数字:1 表示敌人,2 表示空地,0 表示地雷所在的位置。地雷爆炸后,会打中它所在的那一行和那一列上的所有敌人。我们要数一数一共能清除多少个敌人。

    第二步:想清楚要做什么。 其实只要做两件事:第一,找到地雷在哪一行哪一列;第二,数出这一行和这一列上一共有几个 1(敌人)。

    第三步:想出聪明的做法——边读边统计。 不需要把整张地图都存下来。读地图的时候一边读一边统计:遇到 1,就把这一行的敌人计数加 1,同时把这一列的敌人计数加 1;遇到 0,就记下它的行号和列号。全部读完后,答案就是“地雷所在行的敌人数 + 地雷所在列的敌人数”。

    第四步:为什么这样算不会重复? 地雷的位置是 0,不是 1,所以在统计时它不会给任何一行或一列加计数。地雷所在的那个格子虽然既属于行又属于列,但它不是敌人,不会被重复计算。其他格子要么在行里被算一次,要么在列里被算一次,不可能重叠。

    第五步:为什么不存整张地图? 因为最终只用得到地雷所在行和所在列的敌人数量,其他位置的信息读完就没用了。一边读入一边累计,既省内存又直观,这就是“读数据的同时做预处理”的常用技巧。

    第六步:举个例子验证。 用 4×4 的地图,地雷放在第三行第二列。假设第三行的敌人有 2 个,第二列的敌人有 3 个,那么总共能清除 2+3=5 个敌人,和样例输出一致。

    第七步:注意边界情况。 如果地雷所在的行或列上没有敌人,那一部分就是 0,答案就是另一部分的数量;如果整行整列都没有敌人,答案就是 0。题目保证地图中 0 只出现一次(只有一颗地雷)。

    参考代码

    // 安放地雷2:统计地雷所在行、列中敌人(数字1)的总数
    #include <iostream>
    using namespace std;
    
    int rowCnt[1005], colCnt[1005]; // 每行、每列的敌人数量
    
    int main() {
        int n;
        cin >> n;
        int mineRow = -1, mineCol = -1; // 地雷所在的行号和列号
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                int cell;
                cin >> cell;
                if (cell == 1) { // 是敌人,所在行、列计数各加一
                    rowCnt[i]++;
                    colCnt[j]++;
                } else if (cell == 0) { // 0 是地雷位置,记下行号和列号
                    mineRow = i;
                    mineCol = j;
                }
            }
        }
        cout << rowCnt[mineRow] + colCnt[mineCol] << endl; // 行敌人 + 列敌人
        return 0;
    }
    

    复杂度分析

    读入 n×n 个格子,每个格子只处理一次,时间复杂度 O(n²)。空间只用了两个长度为 n 的数组来记录每行、每列的敌人数量,O(n)。

    • 1