小 Z 打地鼠

L2-3 小 Z 打地鼠

题目描述

又逢周日,小 Z 打开了一款打地鼠游戏。

游戏包含一个 n × m n\times m n×m 的网格地图,地图上每个格点都有一个地鼠,每个地鼠都有一个得分。

记第 x x x 行第 y y y 列的格点坐标为 ( x , y ) (x, y) (x,y),其中 1 ≤ x ≤ n 1\leq x\leq n 1xn 1 ≤ y ≤ m 1\leq y\leq m 1ym,记 ( x , y ) (x, y) (x,y) 格点的地鼠的得分为 V ( x , y ) V(x, y) V(x,y)(可以为负数)。

小 Z 用一把旋转了 45 45 45 度的正方形锤子打地鼠,假设小 Z 落锤的位置为 ( x 0 , y 0 ) (x_0, y_0) (x0,y0),则所有坐标满足 ∣ x − x 0 ∣ + ∣ y − y 0 ∣ ≤ d |x - x_0| + |y - y_0|\leq d xx0+yy0d 的位置 ( x , y ) (x, y) (x,y) 的地鼠都会被打掉。

例如:设 n = 10 n = 10 n=10 m = 15 m = 15 m=15 d = 2 d = 2 d=2。蓝色(左上角位置)、青色(中间位置)、黄色(右下角位置)分别表示三种落锤情况下能够打到的格点。
在这里插入图片描述
一次落锤获得的得分是被打到的地鼠的得分的总和,小 Z 想要最大化得分,请你帮他算一算他能够得到的最大得分,以及所有可以得到这个得分的落锤位置坐标。

输入格式

第一行包含三个整数 n , m , d n, m, d n,m,d,与题目描述中所指一致。
接下来 n n n 行,每行 m m m 个数,表示每个格点上的地鼠的得分。

输出格式

第一行输出两个整数 m a x V a l u e , a n s C o u n t \rm maxValue, ansCount maxValue,ansCount,中间用空格隔开,分别表示能够得到的最大得分和可以得到这个得分的落锤位置的数量。

接下来 a n s C o u n t \rm ansCount ansCount 行,每行包含两个整数 x i , y i x_i, y_i xi,yi,表示一个落锤位置坐标。

你需要按照 ( x , y ) (x, y) (x,y) 升序的顺序输出,即 x x x 较小的在前,若 x x x 相同,则 y y y 较小的在前。

样例 #1

样例输入 #1

4 6 1
-3 4 5 4 3 2
1 6 1 7 5 2
9 9 0 0 8 -3
8 8 4 4 -3 2

样例输出 #1

32 1
3 2

提示说明

样例解释:

落锤位置为 ( 3 , 2 ) (3, 2) (3,2),能够打到 ( 2 , 2 ) , ( 3 , 1 ) , ( 3 , 2 ) , ( 3 , 3 ) , ( 4 , 2 ) (2, 2), (3, 1), (3, 2), (3, 3), (4, 2) (2,2),(3,1),(3,2),(3,3),(4,2) 位置的五个地鼠,得分为 6 + 9 + 9 + 0 + 8 = 32 6 + 9 + 9 + 0 + 8 = 32 6+9+9+0+8=32

可以证明不存在其他落锤位置,使得得分 ≥ 32 \geq 32 32

数据规模与约定

对于 40 % 40\% 40% 的数据,保证 1 ≤ n , m ≤ 50 1\leq n, m\leq 50 1n,m50 1 ≤ d ≤ 10 1\leq d\leq 10 1d10
对于 60 % 60\% 60% 的数据,保证 1 ≤ n , m ≤ 400 1\leq n, m\leq 400 1n,m400 1 ≤ d ≤ 10 1\leq d\leq 10 1d10
对于 80 % 80\% 80% 的数据,保证 1 ≤ n , m ≤ 600 1\leq n, m\leq 600 1n,m600 1 ≤ d ≤ 50 1\leq d\leq 50 1d50
对于 100 % 100\% 100% 的数据,保证 1 ≤ n , m ≤ 1000 1\leq n, m\leq 1000 1n,m1000 1 ≤ d ≤ 200 1\leq d\leq 200 1d200 ∣ V ( x , y ) ∣ ≤ 50000 |V(x, y)|\leq 50000 V(x,y)50000

思路提示

对于 40 % 40\% 40%的数据,枚举每个落锤位置,枚举所有格点能否被打到,计算答案,时间复杂度 O ( n 2 m 2 ) O(n^2m^2) O(n2m2)

对于 60 % 60\% 60% 的数据,枚举每个落锤位置,找到所有能被打到的格点,计算答案,时间复杂度 O ( n m d 2 ) O(nmd^2) O(nmd2)

对于 80 % 80\% 80% 的数据,枚举每个落锤位置,对于每个能打到的行都要做区间求和,可以使用一维前缀和求解,时间复杂度 O ( n m d ) O(nmd) O(nmd)

对于 100 % 100\% 100% 的数据,将地图和锤子顺时针旋转 45 45 45 度,多出来的格子得分为 0 0 0 ,再枚举每个落锤位置,使用二维前缀和快速计算所有被打到的格点的得分之和,时间复杂度 O ( n m ) O(nm) O(nm)

代码内容

#include <bits/stdc++.h>
using namespace std;
const int N = 1210;
int n, m, d;
int g[N << 1][N << 1];

pair<int, int> getpos(pair<int, int> p) 
{
	int x = p.first, y = p.second;
	return make_pair(x + y - 1, N + x - y);
}
int calc(int lx, int ly, int rx, int ry) 
{
	lx = max(lx, 1); ly = max(ly, 1);
	return g[rx][ry] - g[rx][ly - 1] - g[lx - 1][ry] + g[lx - 1][ly - 1];
}

signed main() 
{
	scanf("%d%d%d", &n, &m, &d);
	for(int i = 1; i <= n; i++) 
	{
		for(int j = 1; j <= m; j++) 
		{
			int x; scanf("%d", &x);
			pair<int, int> pos = getpos(make_pair(i, j));
			g[pos.first][pos.second] = x;
		}
	}
	cerr << clock() * 1.0 / CLOCKS_PER_SEC << '\n';
	for(int i = 1; i <= n + m + d; i++)
		for(int j = 1; j <= N + n + d; j++)
			g[i][j] = g[i][j - 1] + g[i - 1][j] - g[i - 1][j - 1] + g[i][j];
	int maxVal = -1e9;
	for(int i = 1; i <= n; i++) 
	{
		for(int j = 1; j <= m; j++) 
		{
			pair<int, int> pos = getpos(make_pair(i, j));
			maxVal = max(maxVal, calc(pos.first - d, pos.second - d, pos.first + d, pos.second + d));
		}
	}
	vector<pair<int, int>> ans;
	for(int i = 1; i <= n; i++) 
	{
		for(int j = 1; j <= m; j++) 
		{
			pair<int, int> pos = getpos(make_pair(i, j));
			if(calc(pos.first - d, pos.second - d, pos.first + d, pos.second + d) == maxVal)
				ans.emplace_back(i, j);
		}
	}
	printf("%d %d\n", maxVal, (int)(ans.size()));
	for(auto [x, y] : ans)
		printf("%d %d\n", x, y);
	return 0;
}
  • 19
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Pretty Boy Fox

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值