【动态规划】【广度优先搜索】【逆向思考】【单调向量】2617 网格图中最少访问的格子数

慈云数据 2024-05-30 技术支持 27 0

本文涉及的基础知识点

二分查找算法合集

动态规划汇总

作者推荐

视频算法专题

题目

给你一个下标从 0 开始的 m x n 整数矩阵 grid 。你一开始的位置在 左上角 格子 (0, 0) 。

当你在格子 (i, j) 的时候,你可以移动到以下格子之一:

满足 j first); } auto ij = std::lower_bound(cols[c].begin(), cols[c].end(), r + grid[r][c], Cmp); if (cols[c].end() != ij ) { iPreMin = min(iPreMin, ij->first); } if (INT_MAX == iPreMin) { continue; } Add(r, c, iPreMin + 1); } } return vDis.front().front(); } int m_r, m_c; };

2023年8月版

typedef std::priority_queue QUE;

class Solution {

public:

int minimumVisitedCells(vector& grid) {

m_r = grid.size();

m_c = grid[0].size();

vector vVis(m_r, vector(m_c,INT_MAX));

vVis[0][0] = 1;

vector setCols(m_c);

vector vDelCols(m_c);

for (int r = 0; r

{

for (int c = 0; c

{

auto& setCol = setCols[c];

auto& vDelCol = vDelCols[c];

while (vDelCol.size() && (vDelCol.top().first == r))

{

setCol.erase(setCol.find(vDelCol.top().second));

vDelCol.pop();

}

}

std::multiset setRow;

QUE vDelRow;

auto Add = [&](int r, int c, int dis, int value)

{

if (INT_MAX == dis)

{

return;

}

setRow.emplace(dis);

vDelRow.emplace(c + value + 1, dis);

setCols[c].emplace(dis);

vDelCols[c].emplace(r + value + 1, dis);

};

for (int c = 0; c

{

if (r + c == 0)

{

Add(0, 0, vVis[0][0], grid[r][c]);

continue;

}

while (vDelRow.size() && (vDelRow.top().first == c))

{

setRow.erase(setRow.find(vDelRow.top().second));

vDelRow.pop();

}

if (setRow.size())

{

vVis[r][c] = min(vVis[r][c],*setRow.begin()+1);

}

auto& setCol = setCols[c];

if (setCol.size())

{

vVis[r][c] = min(vVis[r][c], *setCol.begin() + 1);

}

if (INT_MAX == vVis[r][c])

{

continue;

}

Add(r, c, vVis[r][c], grid[r][c]);

}

}

int iRet = vVis.back().back();

return (INT_MAX == iRet) ? -1 : iRet;

}

int m_r, m_c;

};

其它方法

可以用有向图并集查找,寻找没有删除的元素。r1和r2连接,表示[r1,r2)已经全部删除,直接处理r2。

2023年9月版

class Solution {

public:

int minimumVisitedCells(vector& grid) {

m_r = grid.size(), m_c = grid[0].size();

if (m_r * m_c == 1)

{

return 1;

}

vector vvRowMinDis(m_c); // 每列的单调栈

int iRet = m_iNotMay;

for (int r = m_r - 1; r >= 0; r–)

{

std::vector vColMinDis;//列号越来越小,值越来越大

for (int c = m_c - 1; c >= 0; c–)

{

auto& sta = vvRowMinDis[c];

if ((m_r - 1 == r) && (m_c - 1 == c))

{

vColMinDis.emplace_back(c, 1);

sta.emplace_back(r, 1);

continue;

}

int iCurDis = m_iNotMay;

//处理右移

auto it = std::lower_bound(vColMinDis.begin(), vColMinDis.end(), c + grid[r][c], [](const std::pair& p1, int a)

{return p1.first > a; });

if (vColMinDis.end() != it)

{

const int iDis = it->second + 1;

iCurDis = min(iCurDis, iDis);

}

//处理左移

auto ij = std::lower_bound(sta.begin(), sta.end(), r + grid[r][c], [](const std::pair& p1, int a)

{return p1.first > a; });

if (sta.end() != ij)

{

const int iDis = ij->second + 1;

iCurDis = min(iCurDis, iDis);

}

if (m_iNotMay == iCurDis)

{

continue;

}

while (sta.size() && (sta.back().second >= iCurDis))

{

sta.pop_back();

}

sta.emplace_back(r, iCurDis);

while (vColMinDis.size() && (vColMinDis.back().second >= iCurDis))

{

vColMinDis.pop_back();

}

vColMinDis.emplace_back(c, iCurDis);

if (r + c == 0)

{

iRet = iCurDis;

}

}

}

return (iRet >= m_iNotMay ) ? -1 : iRet;

}

int m_r, m_c;

const int m_iNotMay = 1000 * 1000 * 1000;

};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。

https://edu.csdn.net/course/detail/38771

如何你想快

速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程

https://edu.csdn.net/lecturer/6176

相关

下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版

https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17

或者 操作系统:win10 开发环境: VS2022 C++17

如无特殊说明,本算法用**C++**实现。

微信扫一扫加客服

微信扫一扫加客服

点击启动AI问答
Draggable Icon