题意:

在一个 n行 m 列的网格地图中,每个单元格 (i,j) 有初始敌人数量 a i,j​,敌方会进行 q 次增援操作(每次给指定单元格 (x,y)增加 z名敌人)。玉米加农炮的效果是:选择单元格 (x,y),会消灭所有与该单元格曼哈顿距离≤2的单元格内的敌人。 要求在每次增援后,找到能消灭最多敌人的单元格坐标;若有多个最优解,输出任意一个即可。

核心思路:

先定义 a[i][j]:表示选择单元格 (i,j) 发射玉米加农炮时,能消灭的总敌人数量(即曼哈顿距离≤2 的所有单元格敌人数量之和)。 遍历每个初始有敌人的单元格 (i,j)(敌人数量为 t),将 t 累加到所有能覆盖到 (i,j) 的加农炮发射点的 a[nx][ny] 中: 这里的 dx[ ]/dy[ ] 数组枚举了 “曼哈顿距离≤2” 的所有偏移量(共 13 个方向),本质是:单元格 (i,j) 的敌人会被所有距离它≤2 的发射点计入总伤害。 同时维护全局最大值 ma 和对应的坐标 tagx/tagy。 增援操作是给 (x,y) 增加 z 个敌人,同理:这个新增的 z 也需要累加到所有能覆盖到 (x,y) 的发射点的 a[nx][ny] 中。 每次累加后检查是否刷新了全局最大值,若刷新则更新最大值和坐标,最后输出当前最优坐标。

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 510;
int a[N][N];
int n,m,q,ma=-1,tagx,tagy;
int dx[] = {0,-1, 1, 0, 0, 1, 1, -1, -1,-2,2,0,0};
int dy[] = {0,0, 0, -1, 1, 1, -1, -1, 1,0,0,-2,2};
 
void solve(){
    int x,y,z;
    cin>>x>>y>>z;
    for(int f=0;f<13;f++){
        int nx=x+dx[f],ny=y+dy[f];
        if(nx<=0||nx>n||ny<=0||ny>m) continue;
        a[nx][ny]+=z;
        if(ma<a[nx][ny]){
            ma=a[nx][ny];
            tagx=nx;
            tagy=ny;
        }
    }
    cout<<tagx<<" "<<tagy<<"\n";
}
 
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    cin>>n>>m>>q;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            int t;
            cin>>t;
            for(int f=0;f<13;f++){
                int nx=i+dx[f],ny=j+dy[f];
                if(nx<=0||nx>n||ny<=0||ny>m) continue;
                a[nx][ny]+=t;
                if(ma<a[nx][ny]){
                    ma=a[nx][ny];
                    tagx=nx;
                    tagy=ny;
                }
            }
        }
    }
    while(q--){
        solve();
    }
    return 0;
}