【离线查询 堆】2503. 矩阵查询可获得的最大分数

本文涉及知识点

离线查询 堆

LeetCode2503. 矩阵查询可获得的最大分数

给你一个大小为 m x n 的整数矩阵 grid 和一个大小为 k 的数组 queries 。
找出一个大小为 k 的数组 answer ,且满足对于每个整数 queries[i] ,你从矩阵 左上角 单元格开始,重复以下过程:
如果 queries[i] 严格 大于你当前所处位置单元格,如果该单元格是第一次访问,则获得 1 分,并且你可以移动到所有 4 个方向(上、下、左、右)上任一 相邻 单元格。
否则,你不能获得任何分,并且结束这一过程。
在过程结束后,answer[i] 是你可以获得的最大分数。注意,对于每个查询,你可以访问同一个单元格 多次 。
返回结果数组 answer 。
示例 1:

输入:grid = [[1,2,3],[2,5,7],[3,5,1]], queries = [5,6,2]
输出:[5,8,1]
解释:上图展示了每个查询中访问并获得分数的单元格。
示例 2:

输入:grid = [[5,2,1],[1,1,2]], queries = [3]
输出:[0]
解释:无法获得分数,因为左上角单元格的值大于等于 3 。

提示:
m == grid.length
n == grid[i].length
2 <= m, n <= 1000
4 <= m * n <= 105
k == queries.length
1 <= k <= 104
1 <= grid[i][j], queries[i] <= 106

离线查询

对 queries按升序排序,并从小到大处理que。
ret记录所有能访问的单格的数量。
小根堆neiBo 记录所有和能访问的单格相邻的单格信息。包括:值、行、列
如果堆顶元素的值小于que
ret++
相邻的元素加到neiBo。
注意: 类似于BFS,每个单格只入堆一次。

代码

核心代码

class Solution {
public:
	vector<int> maxPoints(vector<vector<int>>& grid, vector<int>& queries) {
		const int R = grid.size(), C = grid[0].size();
		vector<int> indexs(queries.size());
		iota(indexs.begin(), indexs.end(),0);
		sort(indexs.begin(), indexs.end(), [&](int i1, int i2) {return queries[i1] < queries[i2]; });
		priority_queue<tuple<int, int, int>, vector<tuple<int, int, int>>, greater<>> heap;		
		vector<vector<bool>> vis(R, vector<bool>(C));
		auto Add = [&](int r, int c) {
			if (vis[r][c]) { return; }
			heap.emplace(make_tuple(grid[r][c], r, c));
			vis[r][c] = true;
		};
		Add(0, 0);
		int ret = 0;
		vector<int> vRet(queries.size());
		for (int i : indexs) {
			while (heap.size() && (get<0>(heap.top()) < queries[i])) {
				ret++;
				auto [val, r, c] = heap.top();
				heap.pop();
				if (r + 1 < R) {
					Add(r + 1, c);
				}
				if (r >0) {
					Add(r - 1, c);
				}
				if (c + 1 < C) {
					Add(r, c + 1);
				}
				if (c > 0) {
					Add(r, c - 1);
				}
			}
			vRet[i] = ret;
		}
		return vRet;
	}
};

单元测试

template<class T1, class T2>
void AssertEx(const T1& t1, const T2& t2)
{
	Assert::AreEqual(t1, t2);
}

template<class T>
void AssertEx(const vector<T>& v1, const vector<T>& v2)
{
	Assert::AreEqual(v1.size(), v2.size());
	for (int i = 0; i < v1.size(); i++)
	{
		Assert::AreEqual(v1[i], v2[i]);
	}
}

template<class T>
void AssertV2(vector<vector<T>> vv1, vector<vector<T>> vv2)
{
	sort(vv1.begin(), vv1.end());
	sort(vv2.begin(), vv2.end());
	Assert::AreEqual(vv1.size(), vv2.size());
	for (int i = 0; i < vv1.size(); i++)
	{
		AssertEx(vv1[i], vv2[i]);
	}
}

namespace UnitTest
{
	vector<vector<int>> grid;
	vector<int> queries;
	TEST_CLASS(UnitTest)
	{
	public:
		TEST_METHOD(TestMethod001)
		{
			grid = { {1,2,3},{2,5,7},{3,5,1} }, queries = { 5 };
			auto res = Solution().maxPoints(grid, queries);
			AssertEx(vector<int>{5,}, res);
		}
		TEST_METHOD(TestMethod00)
		{
			grid = { {1,2,3},{2,5,7},{3,5,1} }, queries = { 5,6,2 };
			auto res = Solution().maxPoints(grid, queries);
			AssertEx(vector<int>{5, 8, 1}, res);
		}
		TEST_METHOD(TestMethod01)
		{
			grid = { {5,2,1},{1,1,2} }, queries = { 3 };
			auto res = Solution().maxPoints(grid, queries);
			AssertEx(vector<int>{0}, res);
		}
	
	};
}

扩展阅读

视频课程

先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关推荐

我想对大家说的话
喜缺全书算法册》以原理、正确性证明、总结为主。
按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

  • 17
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

闻缺陷则喜何志丹

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

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

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

打赏作者

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

抵扣说明:

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

余额充值