题意:
在一个 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;
}

京公网安备 11010502036488号