2023-03-06:给定一个二维网格 grid ,其中: ‘.‘ 代表一个空房间 ‘#‘ 代表一堵 ‘@‘ 是起点 小写字母代表钥匙 大写字母代表锁 我们从起点开始出发,一次移动是指向四个基本方向之
2023-03-06:给定一个二维网格 grid ,其中:
‘.’ 代表一个空房间
‘#’ 代表一堵
‘@’ 是起点
小写字母代表钥匙
大写字母代表锁
我们从起点开始出发,一次移动是指向四个基本方向之一行走一个单位空间
我们不能在网格外面行走,也无法穿过一堵墙
如果途经一个钥匙,我们就把它捡起来。除非我们手里有对应的钥匙,否则无法通过锁。
假设 k 为 钥匙/锁 的个数,且满足 1 <= k <= 6,
字母表中的前 k 个字母在网格中都有自己对应的一个小写和一个大写字母
换言之,每个锁有唯一对应的钥匙,每个钥匙也有唯一对应的锁
另外,代表钥匙和锁的字母互为大小写并按字母顺序排列
返回获取所有钥匙所需要的移动的最少次数。如果无法获取所有钥匙,返回 -1 。
输入:grid = [“@.a.#”,“###.#”,“b.A.B”]
输出:8
解释:目标是获得所有钥匙,而不是打开所有锁。
来自Airbnb、Uber。
答案2023-03-06:
dijkstra算法。
代码用rust编写。代码如下:
use std::iter::repeat;
fn main() {
let mut grid = vec!["@.a.#", "###.#", "b.A.B"];
let ans = shortestPathAllKeys(&mut grid);
println!("ans = {}", ans);
}
// "@....#"
// "..b..B"
//
// @ . . . . #
// . . B . . B
fn shortestPathAllKeys(grid: &mut Vec<&str>) -> i32 {
let n = grid.len() as i32;
let mut map: Vec<Vec<u8>> = repeat(vec![]).take(n as usize).collect();
for i in 0..grid.len() {
map[i as usize] = grid[i as usize].as_bytes().to_vec();
}
let m = map[0].len() as i32;
return dijkstra(&mut map, n, m);
}
fn dijkstra(map: &mut Vec<Vec<u8>>, n: i32, m: i32) -> i32 {
let mut startX = 0;
let mut startY = 0;
let mut keys = 0;
for i in 0..n {
for j in 0..m {
if map[i as usize][j as usize] == '@' as u8 {
startX = i;
startY = j;
}
if map[i as usize][j as usize] >= 'a' as u8 && map[i as usize][j as usize] <= 'z' as u8
{
keys += 1;
}
}
}
// 如果有4把钥匙
// limit = 0000..00001111
// 如果有5把钥匙
// limit = 0000..00011111
// 也就是说,所有钥匙都凑齐的状态,就是limit
let mut limit = (1 << keys) - 1;
// 用堆来维持走过的点(dijkstra标准操作)
// 维持的信息是一个个小的4维数组,arr
// arr[0] : 当前来到的x坐标
// arr[1] : 当前来到的y坐标
// arr[2] : 当前收集到的钥匙状态
// arr[3] : 从出发点到当前的距离
// 堆根据距离的从小到大组织,距离小根堆
// PriorityQueue<int[]> heap = new PriorityQueue<>((a, b) -> a[3] - b[3]);
let mut heap: Vec<Vec<i32>> = vec![];
let mut visited: Vec<Vec<Vec<bool>>> = repeat(
repeat(repeat(false).take(1 << keys).collect())
.take(m as usize)
.collect(),
)
.take(n as usize)
.collect();
// startX, startY, 000000
heap.push(vec![startX, startY, 0, 0]);
while heap.len() > 0 {
heap.sort_by(|a, b| a[3].cmp(&b[3]));
let cur = heap.pop().unwrap();
let x = cur[0];
let y = cur[1];
let s = cur[2];
let w = cur[3];
if s == limit {
return w;
}
if visited[x as usize][y as usize][s as usize] {
continue;
}
visited[x as usize][y as usize][s as usize] = true;
add(x - 1, y, s, w, n, m, map, &mut visited, &mut heap);
add(x + 1, y, s, w, n, m, map, &mut visited, &mut heap);
add(x, y - 1, s, w, n, m, map, &mut visited, &mut heap);
add(x, y + 1, s, w, n, m, map, &mut visited, &mut heap);
}
return -1;
}
// 当前是由(a,b,s) -> (x,y,状态?)
// w ,从最开始到达(a,b,s)这个点的距离 -> w+1
// n,m 固定参数,防止越界
// map 地图
// visited 访问过的点,不要再加入到堆里去!
// heap, 堆!
fn add(
x: i32,
y: i32,
mut s: i32,
w: i32,
n: i32,
m: i32,
map: &mut Vec<Vec<u8>>,
visited: &mut Vec<Vec<Vec<bool>>>,
heap: &mut Vec<Vec<i32>>,
) {
if x < 0 || x == n || y < 0 || y == m || map[x as usize][y as usize] == '#' as u8 {
return;
}
if map[x as usize][y as usize] >= 'A' as u8 && map[x as usize][y as usize] <= 'Z' as u8 {
// 锁!
// B -> 00000010
// dcba
// x,y,状 = x,y,s
// s == 00001000
// dcba
// A s & (1 << 0) != 0
// B s & (1 << 1) != 0
// D s & (1 << 3) != 0
//
if (!visited[x as usize][y as usize][s as usize]
&& (s & (1 << (map[x as usize][y as usize] - 'A' as u8))) != 0)
{
heap.push(vec![x, y, s, w + 1]);
}
} else {
// 不是锁!
// 要么是钥匙 a b c
// 要么是空房间 .
// 要么是初始位置 @
if map[x as usize][y as usize] >= 'a' as u8 && map[x as usize][y as usize] <= 'z' as u8 {
s |= 1 << (map[x as usize][y as usize] - ('a' as u8)) as i32;
}
if !visited[x as usize][y as usize][s as usize] {
heap.push(vec![x, y, s, w + 1]);
}
}
}
2023-03-06:给定一个二维网格 grid ,其中: ‘.‘ 代表一个空房间 ‘#‘ 代表一堵 ‘@‘ 是起点 小写字母代表钥匙 大写字母代表锁 我们从起点开始出发,一次移动是指向四个基本方向之的更多相关文章
- C语言里的指针探析——type *name[] 在函数参数里面,是一个二维指针
type *name[] 在函数参数里面声明和不在函数里面声明其实不一样. type *name[] 如果在函数参数里声明,则name 是一个二维指针,并不是一个指针数组,而如果不在函数参数里声明,则 ...
- ytu 1050:写一个函数,使给定的一个二维数组(3×3)转置,即行列互换(水题)
1050: 写一个函数,使给定的一个二维数组(3×3)转置,即行列互换 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 154 Solved: 112[ ...
- UDF——处理二维网格的利器:Boost.Geometry库
本文编译工具:VC++ UDF Studio 该插件可以直接在Visual Studio中一键编译.加载.调试UDF源码,极大提高编写排错效率,且支持C++,MFC,Windows API和第三方库, ...
- 二维码合成,将苹果和安卓(ios和android)合成一个二维码,让用户扫描一个二维码就可以分别下载苹果和安卓的应用
因为公司推广的原因,没有合适的将苹果和安卓(ios和android)合成一个二维码的工具. 因为这个不难,主要是根据浏览器的UA进行判断,所以就自己开发了一个网站 网站名称叫:好推二维码 https ...
- [LeetCode] Search a 2D Matrix II 搜索一个二维矩阵之二
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the follo ...
- [LeetCode] Search a 2D Matrix 搜索一个二维矩阵
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the follo ...
- [CareerCup] 11.6 Search a 2D Matrix 搜索一个二维矩阵
11.6 Given an M x N matrix in which each row and each column is sorted in ascending order, write a m ...
- [CareerCup] 13.10 Allocate a 2D Array 分配一个二维数组
13.10 Write a function in C called my2DAlloc which allocates a two-dimensional array. Minimize the n ...
- new一个二维数组
.定义一个二维数组 char **array1 array1 = new char *[x]; for(i=0;i<x;++i) array1[i] = new char[y]; ...用的时候 ...
- 公司开发的APP,如何生成一个二维码,供客户下载使用
1.其实和简单,因为一般的用户使用扫一扫,大多数都是用微信自带的扫一扫工具 而,微信打开的二维码页面,会自动屏蔽apk文件,所以显然把apk的url生成一个二维码,让用户扫一扫就能直接下载,这样是行不 ...
随机推荐
- cider 二面
cider 二面 1.祖传自我介绍 2.当前BLF外卖业务缺点是什么? 产品单一 : 跟竞品比较起来,产品单一导致用户流量很少 3.QLExpress二次开发的原因 流程对接 提升性能 后台对接 4. ...
- vue 作者在2022-2-7起宣布 vue3 正式作为默认版本
vue 作者在2022-2-7起宣布 vue3 正式作为默认版本 vue 作者尤雨溪在知乎上发布一篇文章,宣布 Vue3 将在 2022 年 2 月 7 日 成为新的默认版本! 并且还在文章中做出了一 ...
- c# form-data表单提交,post form上传数据、文件
引用自:https://www.cnblogs.com/DoNetCShap/p/10696277.html 表单提交协议规定:要先将 HTTP 要求的 Content-Type 设为 multipa ...
- gitee使用
1.github的国内跳转 github国内无法直接访问,所以直接使用gitee导入github工程 https://gitee.com/ 2.虚拟机配置ssh公钥 https://gitee ...
- Git 小技巧:忽略某些文件的更改
*以下内容为本人的学习笔记,如需要转载,请声明原文链接微信公众号「ENG八戒」https://mp.weixin.qq.com/s/dp9Mwq7vf0ASF_FftBN8Ww 作为一枚合格的代码贡献 ...
- 痞子衡嵌入式:盘点国内RISC-V内核MCU厂商(2021年发布产品)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是国内RISC-V内核MCU厂商(2021). 虽然RISC-V风潮已经吹了好几年,但2019年才是其真正进入主流市场的元年,最近国内大量 ...
- 继续Vue的探索
接上集 上次到了想要利用Vue实现隔行变色的请求,但是由于使用的代码过于"高级"导致无法识别,这就需要利用webpack来解决它! webpack的基本使用 1.首先,在项目中安装 ...
- 基于声网 Flat 构建白板插件应用“成语解谜”的最佳实践
前言 本文作者赵杭天.他参加了"2022 RTE 编程挑战赛"--"赛道二 场景化白板插件应用开发" , 并凭借作品"成语解谜"获得了该赛道 ...
- ElasticSearch 实现分词全文检索 - 聚合查询 cardinality
目录 ElasticSearch 实现分词全文检索 - 概述 ElasticSearch 实现分词全文检索 - ES.Kibana.IK安装 ElasticSearch 实现分词全文检索 - Rest ...
- Easy App Locker - 给你的 mac 应用加锁保护你的隐私
Easy App Locker可以对Mac上的单个应用进行密码保护.维护Mac上的隐私. 像如果你的某个应用存在隐私数据就可以使用该软件将此应用上锁,这样当你的朋友使用你的 mac 时你就不用担心你的 ...