G. Mischievous Shooter
G. Mischievous Shooter
Once the mischievous and wayward shooter named Shel found himself on a rectangular field of size , divided into unit squares. Each cell either contains a target or not.
Shel only had a lucky shotgun with him, with which he can shoot in one of the four directions: right-down, left-down, left-up, or right-up. When fired, the shotgun hits all targets in the chosen direction, the Manhattan distance to which does not exceed a fixed constant . The Manhattan distance between two points and is equal to .

Possible hit areas for .
Shel's goal is to hit as many targets as possible. Please help him find this value.
Input
Each test consists of several test cases. The first line contains a single integer () — the number of test cases. Then follows the description of the test cases.
The first line of each test case contains field dimensions , , and the constant for the shotgun's power ().
Each of the next lines contains characters — the description of the next field row, where the character '.' means the cell is empty, and the character '#' indicates the presence of a target.
It is guaranteed that the sum of over all test cases does not exceed .
Output
For each test case, output a single integer on a separate line, which is equal to the maximum possible number of hit targets with one shot.
Example
input
4
3 3 1
.#.
###
.#.
2 5 3
###..
...##
4 4 2
..##
###.
#..#
####
2 1 3
#
#
output
3
4
5
2
Note
Possible optimal shots for the examples in the statement:

解题思路
看完题就很快想到做法了,很明显就是枚举每个格子然后用前缀和求四个方向的三角形中 #
的数量,但想到会有很多边界情况代码很难写就不做了。
为了少写些代码,我们可以固定一个三角形的方向,通过将矩阵顺时针旋转 来实现其他方向的枚举过程,这样就可以用同一套代码逻辑来处理四个方向的问题。为了方便这里选择左下角的方向。
三角形内的 #
用前缀和来维护,当从 变到 时,变化的部分入下图。绿色的部分是新增的,红色的部分是删掉的。
所以我们只需维护两个前缀和,一个是列方向的用 表示第 列的 行内 #
的数量,转移方程是 。另外一个是对角线方向的用 表示从 沿截距为 的直线左上方的 #
的数量,转移方程是 。
用 表示 左下方三角形内 #
的数量,当枚举到下一个格子 时,令 ,那么 就变成 。考虑边界情况,当 ,在 中只需变成 即可。在 中,令 ,,则需要将 减去 变成 ,对应的 也要减去 。如果变化后的 小于 则变成 即可。因此实际上 应该变成
最后就是如何矩阵顺时针旋转 。举个例子模拟一下,可以发现原本的 就会变成 。
AC 代码代码如下,时间复杂度为 :
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
void solve() {
int n, m, k;
cin >> n >> m >> k;
vector<string> g(n);
for (int i = 0; i < n; i++) {
cin >> g[i];
}
int ret = 0;
for (int i = 0; i < 4; i++) {
vector<vector<int>> s1(n + 1, vector<int>(m + 1)), s2(n + 1, vector<int>(m + 1));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (g[i - 1][j - 1] == '#') s1[i][j] = s2[i][j] = 1;
s1[i][j] += s1[i - 1][j];
s2[i][j] += s2[i - 1][j - 1];
}
}
for (int i = 1; i <= n; i++) {
int s = 0;
for (int j = 1; j <= m; j++) {
s += s1[min(n, i + k)][j] - s1[i - 1][j];
s -= s2[min(n, i + k)][max(0, j - 1 - max(0, i + k - n))] - s2[i - 1][max(0, j - k - 2)];
ret = max(ret, s);
}
}
vector<string> f(m, string(n, 0));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
f[j][n - i - 1] = g[i][j];
}
}
g = f;
swap(n, m);
}
cout << ret << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
参考资料
Codeforces Round 920 (Div. 3) A-G 讲解:https://www.bilibili.com/video/BV19C4y1k7MA/
Editorial for Codeforces Round 920 (Div. 3):https://codeforces.com/blog/entry/124757
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17985928
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效