图-最短路-dijkstra-0/1BFS-1368. 使网格图至少有一条有效路径的最小代价
2020-03-01 22:59:59
问题描述:
给你一个 m x n 的网格图 grid 。 grid 中每个格子都有一个数字,对应着从该格子出发下一步走的方向。 grid[i][j] 中的数字可能为以下几种情况:
- 1 ,下一步往右走,也就是你会从
grid[i][j]走到grid[i][j + 1] - 2 ,下一步往左走,也就是你会从
grid[i][j]走到grid[i][j - 1] - 3 ,下一步往下走,也就是你会从
grid[i][j]走到grid[i + 1][j] - 4 ,下一步往上走,也就是你会从
grid[i][j]走到grid[i - 1][j]
注意网格图中可能会有 无效数字 ,因为它们可能指向 grid 以外的区域。
一开始,你会从最左上角的格子 (0,0) 出发。我们定义一条 有效路径 为从格子 (0,0) 出发,每一步都顺着数字对应方向走,最终在最右下角的格子 (m - 1, n - 1) 结束的路径。有效路径 不需要是最短路径 。
你可以花费 cost = 1 的代价修改一个格子中的数字,但每个格子中的数字 只能修改一次 。
请你返回让网格图至少有一条有效路径的最小代价。
示例 1:

输入:grid = [[1,1,1,1],[2,2,2,2],[1,1,1,1],[2,2,2,2]]
输出:3
解释:你将从点 (0, 0) 出发。
到达 (3, 3) 的路径为: (0, 0) --> (0, 1) --> (0, 2) --> (0, 3) 花费代价 cost = 1 使方向向下 --> (1, 3) --> (1, 2) --> (1, 1) --> (1, 0) 花费代价 cost = 1 使方向向下 --> (2, 0) --> (2, 1) --> (2, 2) --> (2, 3) 花费代价 cost = 1 使方向向下 --> (3, 3)
总花费为 cost = 3.
示例 2:

输入:grid = [[1,1,3],[3,2,2],[1,1,4]]
输出:0
解释:不修改任何数字你就可以从 (0, 0) 到达 (2, 2) 。
提示:
m == grid.lengthn == grid[i].length1 <= m, n <= 100
问题求解:
最重要的是reduce,如何将问题转成已知的知识非常重要。
本题中看似是需要求改变方向个数最少,其实是在最短路径。
如果我们将通过标示到达w = 0,那么通过修改到达的w = 1。
解法一:dijkstra
朴素的dijkstra算法的时间复杂度为O(V ^ 2);如果使用优先队列和邻接表可以将时间复杂度优化为O((E + V)logV)。
时间复杂度:O(mnlog(mn))
int[][] dirs = new int[][]{{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
public int minCost(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
int[] dist = new int[m * n];
Arrays.fill(dist, (int)(1e9));
PriorityQueue<int[]> pq = new PriorityQueue<>((int[] o1, int[] o2) -> o1[1] - o2[1]);
int[] used = new int[m * n];
pq.add(new int[]{0, 0});
while (!pq.isEmpty()) {
int[] node = pq.poll();
int from = node[0];
int d = node[1];
if (used[from] == 1) continue;
used[from] = 1;
dist[from] = d;
int x = from / n;
int y = from % n;
for (int i = 1; i <= 4; i++) {
int nx = x + dirs[i - 1][0];
int ny = y + dirs[i - 1][1];
if (nx >= m || nx < 0 || ny >= n || ny < 0) continue;
int w = grid[x][y] == i ? 0 : 1;
int to = nx * n + ny;
if (dist[to] > dist[from] + w) {
dist[to] = dist[from] + w;
pq.add(new int[]{to, dist[to]});
}
}
}
return dist[m * n - 1];
}
解法二:0-1BFS
本题有个特殊的地方就是边权重只为0 / 1,在这样的图上求解最短路径的最优解是使用0-1 BFS。
0-1BFS使用了BFS的性质,当前层和下一层的节点的距离最大不超过1,因此当我们碰到w = 0的节点的时候可将其加入队首,如果碰到w = 1的节点的时候将其加入队尾,这样就巧妙的进行了排序工作,因此时间复杂度要更优。
时间复杂度:O(mn)
int[][] dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
public int minCost(int[][] grid) {
int res = 0;
int m = grid.length;
int n = grid[0].length;
if (m == 1 && n == 1) return res;
Deque<int[]> q = new LinkedList<>();
Set<Integer> used = new HashSet<>();
q.add(new int[]{0, 0});
while (!q.isEmpty()) {
int[] curr = q.pollFirst();
if (used.contains(curr[0])) continue;
used.add(curr[0]);
int x = curr[0] / n;
int y = curr[0] % n;
int cost = curr[1];
if (x == m - 1 && y == n - 1) return cost;
for (int i = 1; i <= 4; i++) {
int nx = x + dirs[i - 1][0];
int ny = y + dirs[i - 1][1];
if (nx < 0 || nx >= m || ny < 0 || ny >= n || used.contains(nx * n + ny)) continue;
if (grid[x][y] == i)
q.addFirst(new int[]{nx * n + ny, cost});
else
q.addLast(new int[]{nx * n + ny, cost + 1});
}
}
return -1;
}
图-最短路-dijkstra-0/1BFS-1368. 使网格图至少有一条有效路径的最小代价的更多相关文章
- BZOJ 1579: [Usaco2009 Feb]Revamping Trails 道路升级 分层图最短路 + Dijkstra
Description 每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M(1<=M<=50,000)条双向泥土道路,编号为1..M. 道路i连接牛棚P1_i和P2_i ...
- Codeforces.786B.Legacy(线段树优化建图 最短路Dijkstra)
题目链接 \(Description\) 有\(n\)个点.你有\(Q\)种项目可以选择(边都是有向边,每次给定\(t,u,v/lr,w\)): t==1,建一条\(u\to v\)的边,花费\(w\ ...
- [JLOI2011]飞行路线 分层图最短路
题目描述: Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公司一共在nn个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一 ...
- Bzoj 2834: 回家的路 dijkstra,堆优化,分层图,最短路
2834: 回家的路 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 62 Solved: 38[Submit][Status][Discuss] D ...
- BZOJ_2662_[BeiJing wc2012]冻结_分层图最短路
BZOJ_2662_[BeiJing wc2012]冻结_分层图最短路 Description “我要成为魔法少女!” “那么,以灵魂为代价,你希望得到什么?” “我要将有关魔法和奇迹的一切, ...
- BZOJ2662[BeiJing wc2012]冻结——分层图最短路
题目描述 “我要成为魔法少女!” “那么,以灵魂为代价,你希望得到什么?” “我要将有关魔法和奇迹的一切,封印于卡片之中„„” 在这个愿望被实现以后的世界里,人们享受着魔法卡片(Spe ...
- 分层图最短路【bzoj2662】[BeiJing wc2012]冻结
分层图最短路[bzoj2662][BeiJing wc2012]冻结 Description "我要成为魔法少女!" "那么,以灵魂为代价,你希望得到什么?" ...
- P2939 [USACO09FEB]改造路[分层图最短路]
题意翻译 约翰一共有N)个牧场.由M条布满尘埃的小径连接.小径可 以双向通行.每天早上约翰从牧场1出发到牧场N去给奶牛检查身体. 通过每条小径都需要消耗一定的时间.约翰打算升级其中K条小径,使之成为高 ...
- poj3635Full Tank?[分层图最短路]
Full Tank? Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7248 Accepted: 2338 Descri ...
随机推荐
- Java中间件之RMI及实例介绍 · zijian's blog
RMI介绍 远程方法调用(Remote Method Invocation)是Sun公司规定的允许在不同的JAVA虚拟机之间进行对象间通信的一种规范.在RMI中,JVM可以位于一个或多个计算机上, ...
- 在GitHub上分享自己的项目
GitHub主要是用作基于Git的分布式版本管理系统的库,可以保存和管理自己的代码,而且主要用作代码的合作开发. 注册GitHub后你就会有0.3G的免费空间,不过只能创建公开项目,这也满足代码分享的 ...
- diary20180428
17:05:59 今天早晨去了图书馆.学习了一把vscode.试图在河边看电脑,总有小虫不让我专心. 23:27:34 看纯黑直播打战神,有点感触. 动漫或游戏,角色觉醒,实力大增,小时候(甚至现在) ...
- JSON parse error: Cannot deserialize value of type `java.util.Date` from String
DateTimePicker + @DateTimeFormat("yyyy-MM-dd HH:mm:ss")日期格式转换异常 最近在做的一个项目使用的日期格式是yyyy-MM-d ...
- Flutter Widgets 之 ListWheelScrollView
注意:无特殊说明,Flutter版本及Dart版本如下: Flutter版本: 1.12.13+hotfix.5 Dart版本: 2.7.0 基础用法 在展示大量数据的时候我们第一会想到使用ListV ...
- C与C++面试易出知识点
.1. char c = '\72'; 中的\72代表一个字符,72是八进制数,代表ASCII码字符":". 2. 10*a++ 中a先进行乘法运算再自增(笔试中经常喜欢出这类运算 ...
- Java入门教程七(数组)
数组是最常见的一种数据结构,它是相同类型的用一个标识符封装到一起的基本类型数据序列或者对象序列.数组使用一个统一的数组名和不同的下标来唯一确定数组中的元素.实质上,数组是一个简单的线性序列,因此访问速 ...
- java单链表的实现自己动手写一个单链表
单链表:单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素.链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是 ...
- linux同步当前网络时间
[root@root ~]# yum install -y ntpdate 执行:ntpdate[root@root ~]# ntpdate 120.24.81.91或[root@root ~]# n ...
- SQLyog试用到期的解决方法(仅供个人学习使用,禁止转载或用于商业盈利)
作者:EzrealYi 本章链接:https://www.cnblogs.com/ezrealyi/p/12434105.html win+r->输入regedit->进入注册表 在计算机 ...