From 66f8ec0f91f7cecfec142f1cb79413d30286d73c Mon Sep 17 00:00:00 2001 From: acbin <44314231+acbin@users.noreply.github.com> Date: Thu, 21 Dec 2023 08:51:30 +0800 Subject: [PATCH 1/2] feat: add new lc problem (#2133) --- .../README.md | 98 +++++++++++++++++++ .../README_EN.md | 90 +++++++++++++++++ solution/README.md | 1 + solution/README_EN.md | 1 + solution/summary.md | 1 + solution/summary_en.md | 1 + 6 files changed, 192 insertions(+) create mode 100644 solution/2900-2999/2969.Minimum Number of Coins for Fruits II/README.md create mode 100644 solution/2900-2999/2969.Minimum Number of Coins for Fruits II/README_EN.md diff --git a/solution/2900-2999/2969.Minimum Number of Coins for Fruits II/README.md b/solution/2900-2999/2969.Minimum Number of Coins for Fruits II/README.md new file mode 100644 index 0000000000000..050a765c6f095 --- /dev/null +++ b/solution/2900-2999/2969.Minimum Number of Coins for Fruits II/README.md @@ -0,0 +1,98 @@ +# [2969. Minimum Number of Coins for Fruits II](https://leetcode.cn/problems/minimum-number-of-coins-for-fruits-ii) + +[English Version](/solution/2900-2999/2969.Minimum%20Number%20of%20Coins%20for%20Fruits%20II/README_EN.md) + +## 题目描述 + + + +

You are at a fruit market with different types of exotic fruits on display.

+ +

You are given a 1-indexed array prices, where prices[i] denotes the number of coins needed to purchase the ith fruit.

+ +

The fruit market has the following offer:

+ + + +

Note that even if you can take fruit j for free, you can still purchase it for prices[j] coins to receive a new offer.

+ +

Return the minimum number of coins needed to acquire all the fruits.

+ +

 

+

Example 1:

+ +
+Input: prices = [3,1,2]
+Output: 4
+Explanation: You can acquire the fruits as follows:
+- Purchase the 1st fruit with 3 coins, and you are allowed to take the 2nd fruit for free.
+- Purchase the 2nd fruit with 1 coin, and you are allowed to take the 3rd fruit for free.
+- Take the 3rd fruit for free.
+Note that even though you were allowed to take the 2nd fruit for free, you purchased it because it is more optimal.
+It can be proven that 4 is the minimum number of coins needed to acquire all the fruits.
+
+ +

Example 2:

+ +
+Input: prices = [1,10,1,1]
+Output: 2
+Explanation: You can acquire the fruits as follows:
+- Purchase the 1st fruit with 1 coin, and you are allowed to take the 2nd fruit for free.
+- Take the 2nd fruit for free.
+- Purchase the 3rd fruit for 1 coin, and you are allowed to take the 4th fruit for free.
+- Take the 4th fruit for free.
+It can be proven that 2 is the minimum number of coins needed to acquire all the fruits.
+
+ +

 

+

Constraints:

+ + + +## 解法 + + + + + +### **Python3** + + + +```python + +``` + +### **Java** + + + +```java + +``` + +### **C++** + +```cpp + +``` + +### **Go** + +```go + +``` + +### **...** + +``` + +``` + + diff --git a/solution/2900-2999/2969.Minimum Number of Coins for Fruits II/README_EN.md b/solution/2900-2999/2969.Minimum Number of Coins for Fruits II/README_EN.md new file mode 100644 index 0000000000000..87c6ae17be4db --- /dev/null +++ b/solution/2900-2999/2969.Minimum Number of Coins for Fruits II/README_EN.md @@ -0,0 +1,90 @@ +# [2969. Minimum Number of Coins for Fruits II](https://leetcode.com/problems/minimum-number-of-coins-for-fruits-ii) + +[中文文档](/solution/2900-2999/2969.Minimum%20Number%20of%20Coins%20for%20Fruits%20II/README.md) + +## Description + +

You are at a fruit market with different types of exotic fruits on display.

+ +

You are given a 1-indexed array prices, where prices[i] denotes the number of coins needed to purchase the ith fruit.

+ +

The fruit market has the following offer:

+ + + +

Note that even if you can take fruit j for free, you can still purchase it for prices[j] coins to receive a new offer.

+ +

Return the minimum number of coins needed to acquire all the fruits.

+ +

 

+

Example 1:

+ +
+Input: prices = [3,1,2]
+Output: 4
+Explanation: You can acquire the fruits as follows:
+- Purchase the 1st fruit with 3 coins, and you are allowed to take the 2nd fruit for free.
+- Purchase the 2nd fruit with 1 coin, and you are allowed to take the 3rd fruit for free.
+- Take the 3rd fruit for free.
+Note that even though you were allowed to take the 2nd fruit for free, you purchased it because it is more optimal.
+It can be proven that 4 is the minimum number of coins needed to acquire all the fruits.
+
+ +

Example 2:

+ +
+Input: prices = [1,10,1,1]
+Output: 2
+Explanation: You can acquire the fruits as follows:
+- Purchase the 1st fruit with 1 coin, and you are allowed to take the 2nd fruit for free.
+- Take the 2nd fruit for free.
+- Purchase the 3rd fruit for 1 coin, and you are allowed to take the 4th fruit for free.
+- Take the 4th fruit for free.
+It can be proven that 2 is the minimum number of coins needed to acquire all the fruits.
+
+ +

 

+

Constraints:

+ + + +## Solutions + + + +### **Python3** + +```python + +``` + +### **Java** + +```java + +``` + +### **C++** + +```cpp + +``` + +### **Go** + +```go + +``` + +### **...** + +``` + +``` + + diff --git a/solution/README.md b/solution/README.md index aea51e28c1ce8..92aebda9a4d27 100644 --- a/solution/README.md +++ b/solution/README.md @@ -2979,6 +2979,7 @@ | 2966 | [划分数组并满足最大差限制](/solution/2900-2999/2966.Divide%20Array%20Into%20Arrays%20With%20Max%20Difference/README.md) | | 中等 | 第 376 场周赛 | | 2967 | [使数组成为等数数组的最小代价](/solution/2900-2999/2967.Minimum%20Cost%20to%20Make%20Array%20Equalindromic/README.md) | | 中等 | 第 376 场周赛 | | 2968 | [执行操作使频率分数最大](/solution/2900-2999/2968.Apply%20Operations%20to%20Maximize%20Frequency%20Score/README.md) | | 困难 | 第 376 场周赛 | +| 2969 | [Minimum Number of Coins for Fruits II](/solution/2900-2999/2969.Minimum%20Number%20of%20Coins%20for%20Fruits%20II/README.md) | | 困难 | 🔒 | ## 版权 diff --git a/solution/README_EN.md b/solution/README_EN.md index fbaba2fd8a2cf..7b5d9d2041d36 100644 --- a/solution/README_EN.md +++ b/solution/README_EN.md @@ -2977,6 +2977,7 @@ Press Control + F(or Command + F on | 2966 | [Divide Array Into Arrays With Max Difference](/solution/2900-2999/2966.Divide%20Array%20Into%20Arrays%20With%20Max%20Difference/README_EN.md) | | Medium | Weekly Contest 376 | | 2967 | [Minimum Cost to Make Array Equalindromic](/solution/2900-2999/2967.Minimum%20Cost%20to%20Make%20Array%20Equalindromic/README_EN.md) | | Medium | Weekly Contest 376 | | 2968 | [Apply Operations to Maximize Frequency Score](/solution/2900-2999/2968.Apply%20Operations%20to%20Maximize%20Frequency%20Score/README_EN.md) | | Hard | Weekly Contest 376 | +| 2969 | [Minimum Number of Coins for Fruits II](/solution/2900-2999/2969.Minimum%20Number%20of%20Coins%20for%20Fruits%20II/README_EN.md) | | Hard | 🔒 | ## Copyright diff --git a/solution/summary.md b/solution/summary.md index 78016bbc0885b..2b755cca6ddff 100644 --- a/solution/summary.md +++ b/solution/summary.md @@ -3026,3 +3026,4 @@ - [2966.划分数组并满足最大差限制](/solution/2900-2999/2966.Divide%20Array%20Into%20Arrays%20With%20Max%20Difference/README.md) - [2967.使数组成为等数数组的最小代价](/solution/2900-2999/2967.Minimum%20Cost%20to%20Make%20Array%20Equalindromic/README.md) - [2968.执行操作使频率分数最大](/solution/2900-2999/2968.Apply%20Operations%20to%20Maximize%20Frequency%20Score/README.md) + - [2969.Minimum Number of Coins for Fruits II](/solution/2900-2999/2969.Minimum%20Number%20of%20Coins%20for%20Fruits%20II/README.md) diff --git a/solution/summary_en.md b/solution/summary_en.md index 4a4cb39a6461a..20d4043d71baf 100644 --- a/solution/summary_en.md +++ b/solution/summary_en.md @@ -3026,3 +3026,4 @@ - [2966.Divide Array Into Arrays With Max Difference](/solution/2900-2999/2966.Divide%20Array%20Into%20Arrays%20With%20Max%20Difference/README_EN.md) - [2967.Minimum Cost to Make Array Equalindromic](/solution/2900-2999/2967.Minimum%20Cost%20to%20Make%20Array%20Equalindromic/README_EN.md) - [2968.Apply Operations to Maximize Frequency Score](/solution/2900-2999/2968.Apply%20Operations%20to%20Maximize%20Frequency%20Score/README_EN.md) + - [2969.Minimum Number of Coins for Fruits II](/solution/2900-2999/2969.Minimum%20Number%20of%20Coins%20for%20Fruits%20II/README_EN.md) From 64b25ee311c5ce489f7ceedf1811e5060ac3d07a Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Thu, 21 Dec 2023 08:58:18 +0800 Subject: [PATCH 2/2] feat: add solutions to lc problem: No.1778 (#2134) No.1778.Shortest Path in a Hidden Grid --- .../README.md | 163 ++++++++++++----- .../README_EN.md | 165 +++++++++++++----- .../Solution.cpp | 64 +++++++ .../Solution.java | 123 ++++++------- .../Solution.py | 109 ++++++------ 5 files changed, 408 insertions(+), 216 deletions(-) create mode 100644 solution/1700-1799/1778.Shortest Path in a Hidden Grid/Solution.cpp diff --git a/solution/1700-1799/1778.Shortest Path in a Hidden Grid/README.md b/solution/1700-1799/1778.Shortest Path in a Hidden Grid/README.md index 3ca2c4a1f077c..9bc5ec30c9ab8 100644 --- a/solution/1700-1799/1778.Shortest Path in a Hidden Grid/README.md +++ b/solution/1700-1799/1778.Shortest Path in a Hidden Grid/README.md @@ -92,7 +92,15 @@ The robot is initially standing on cell (1, 0), denoted by the -1. **方法一:DFS 建图 + BFS 求最短路** -相似题目:[1810. 隐藏网格下的最小消耗路径](/solution/1800-1899/1810.Minimum%20Path%20Cost%20in%20a%20Hidden%20Grid/README.md) +我们不妨假设机器人从坐标 $(0, 0)$ 出发,那么我们可以通过 DFS,找到所有可达的坐标,记录在哈希表 $vis$ 中。另外,我们还需要记录终点的坐标 $target$。 + +如果找不到终点,那么直接返回 $-1$。否则,我们可以通过 BFS,求出最短路。 + +时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是网格的行数和列数。 + +相似题目: + +- [1810. 隐藏网格下的最小消耗路径](/solution/1800-1899/1810.Minimum%20Path%20Cost%20in%20a%20Hidden%20Grid/README.md) @@ -118,31 +126,28 @@ The robot is initially standing on cell (1, 0), denoted by the -1. class Solution(object): - def findShortestPath(self, master: 'GridMaster') -> int: - def dfs(i, j): - nonlocal target + def findShortestPath(self, master: "GridMaster") -> int: + def dfs(i: int, j: int): if master.isTarget(): + nonlocal target target = (i, j) - for dir, ndir, a, b in dirs: - x, y = i + a, j + b - if master.canMove(dir) and (x, y) not in s: - s.add((x, y)) - master.move(dir) + return + for k, c in enumerate(s): + x, y = i + dirs[k], j + dirs[k + 1] + if master.canMove(c) and (x, y) not in vis: + vis.add((x, y)) + master.move(c) dfs(x, y) - master.move(ndir) + master.move(s[(k + 2) % 4]) + s = "URDL" + dirs = (-1, 0, 1, 0, -1) target = None - s = set() - dirs = [ - ['U', 'D', -1, 0], - ['D', 'U', 1, 0], - ['L', 'R', 0, -1], - ['R', 'L', 0, 1], - ] + vis = set() dfs(0, 0) if target is None: return -1 - s.remove((0, 0)) + vis.discard((0, 0)) q = deque([(0, 0)]) ans = -1 while q: @@ -151,10 +156,10 @@ class Solution(object): i, j = q.popleft() if (i, j) == target: return ans - for _, _, a, b in dirs: + for a, b in pairwise(dirs): x, y = i + a, j + b - if (x, y) in s: - s.remove((x, y)) + if (x, y) in vis: + vis.remove((x, y)) q.append((x, y)) return -1 ``` @@ -175,37 +180,31 @@ class Solution(object): */ class Solution { - private static final char[] dir = {'U', 'R', 'D', 'L'}; - private static final char[] ndir = {'D', 'L', 'U', 'R'}; - private static final int[] dirs = {-1, 0, 1, 0, -1}; - private static final int N = 1010; - private Set s; private int[] target; + private GridMaster master; + private final int n = 2010; + private final String s = "URDL"; + private final int[] dirs = {-1, 0, 1, 0, -1}; + private final Set vis = new HashSet<>(); public int findShortestPath(GridMaster master) { - target = null; - s = new HashSet<>(); - s.add(0); - dfs(0, 0, master); + this.master = master; + dfs(0, 0); if (target == null) { return -1; } - s.remove(0); + vis.remove(0); Deque q = new ArrayDeque<>(); q.offer(new int[] {0, 0}); - int ans = -1; - while (!q.isEmpty()) { - ++ans; - for (int n = q.size(); n > 0; --n) { - int[] p = q.poll(); - int i = p[0], j = p[1]; - if (target[0] == i && target[1] == j) { + for (int ans = 0; !q.isEmpty(); ++ans) { + for (int m = q.size(); m > 0; --m) { + var p = q.poll(); + if (p[0] == target[0] && p[1] == target[1]) { return ans; } for (int k = 0; k < 4; ++k) { - int x = i + dirs[k], y = j + dirs[k + 1]; - if (s.contains(x * N + y)) { - s.remove(x * N + y); + int x = p[0] + dirs[k], y = p[1] + dirs[k + 1]; + if (vis.remove(x * n + y)) { q.offer(new int[] {x, y}); } } @@ -214,24 +213,92 @@ class Solution { return -1; } - private void dfs(int i, int j, GridMaster master) { + private void dfs(int i, int j) { if (master.isTarget()) { target = new int[] {i, j}; + return; } for (int k = 0; k < 4; ++k) { - char d = dir[k], nd = ndir[k]; int x = i + dirs[k], y = j + dirs[k + 1]; - if (master.canMove(d) && !s.contains(x * N + y)) { - s.add(x * N + y); - master.move(d); - dfs(x, y, master); - master.move(nd); + if (master.canMove(s.charAt(k)) && vis.add(x * n + y)) { + master.move(s.charAt(k)); + dfs(x, y); + master.move(s.charAt((k + 2) % 4)); } } } } ``` +### **C++** + +```cpp +/** + * // This is the GridMaster's API interface. + * // You should not implement it, or speculate about its implementation + * class GridMaster { + * public: + * bool canMove(char direction); + * void move(char direction); + * boolean isTarget(); + * }; + */ + +class Solution { +private: + const int n = 2010; + int dirs[5] = {-1, 0, 1, 0, -1}; + string s = "URDL"; + int target; + unordered_set vis; + +public: + int findShortestPath(GridMaster& master) { + target = n * n; + vis.insert(0); + dfs(0, 0, master); + if (target == n * n) { + return -1; + } + vis.erase(0); + queue> q; + q.emplace(0, 0); + for (int ans = 0; q.size(); ++ans) { + for (int m = q.size(); m; --m) { + auto [i, j] = q.front(); + q.pop(); + if (i * n + j == target) { + return ans; + } + for (int k = 0; k < 4; ++k) { + int x = i + dirs[k], y = j + dirs[k + 1]; + if (vis.count(x * n + y)) { + vis.erase(x * n + y); + q.emplace(x, y); + } + } + } + } + return -1; + } + + void dfs(int i, int j, GridMaster& master) { + if (master.isTarget()) { + target = i * n + j; + } + for (int k = 0; k < 4; ++k) { + int x = i + dirs[k], y = j + dirs[k + 1]; + if (master.canMove(s[k]) && !vis.count(x * n + y)) { + vis.insert(x * n + y); + master.move(s[k]); + dfs(x, y, master); + master.move(s[(k + 2) % 4]); + } + } + } +}; +``` + ### **...** ``` diff --git a/solution/1700-1799/1778.Shortest Path in a Hidden Grid/README_EN.md b/solution/1700-1799/1778.Shortest Path in a Hidden Grid/README_EN.md index 22f5c949574da..4bac1d9e7321f 100644 --- a/solution/1700-1799/1778.Shortest Path in a Hidden Grid/README_EN.md +++ b/solution/1700-1799/1778.Shortest Path in a Hidden Grid/README_EN.md @@ -86,6 +86,18 @@ We now know that the target is the cell (0, 1), and the shortest path to the tar ## Solutions +**Solution 1: DFS for Graph Construction + BFS for Shortest Path** + +We can assume that the robot starts from the coordinate $(0, 0)$. Then, we can use DFS to find all reachable coordinates and record them in the hash table $vis$. In addition, we also need to record the coordinates of the endpoint $target$. + +If the endpoint cannot be found, we directly return $-1$. Otherwise, we can use BFS to find the shortest path. + +The time complexity is $O(m \times n)$, and the space complexity is $O(m \times n)$. Where $m$ and $n$ are the number of rows and columns of the grid, respectively. + +Similar problems: + +- [1810. Minimum Path Cost in a Hidden Grid](/solution/1800-1899/1810.Minimum%20Path%20Cost%20in%20a%20Hidden%20Grid/README_EN.md) + ### **Python3** @@ -108,31 +120,28 @@ We now know that the target is the cell (0, 1), and the shortest path to the tar class Solution(object): - def findShortestPath(self, master: 'GridMaster') -> int: - def dfs(i, j): - nonlocal target + def findShortestPath(self, master: "GridMaster") -> int: + def dfs(i: int, j: int): if master.isTarget(): + nonlocal target target = (i, j) - for dir, ndir, a, b in dirs: - x, y = i + a, j + b - if master.canMove(dir) and (x, y) not in s: - s.add((x, y)) - master.move(dir) + return + for k, c in enumerate(s): + x, y = i + dirs[k], j + dirs[k + 1] + if master.canMove(c) and (x, y) not in vis: + vis.add((x, y)) + master.move(c) dfs(x, y) - master.move(ndir) + master.move(s[(k + 2) % 4]) + s = "URDL" + dirs = (-1, 0, 1, 0, -1) target = None - s = set() - dirs = [ - ['U', 'D', -1, 0], - ['D', 'U', 1, 0], - ['L', 'R', 0, -1], - ['R', 'L', 0, 1], - ] + vis = set() dfs(0, 0) if target is None: return -1 - s.remove((0, 0)) + vis.discard((0, 0)) q = deque([(0, 0)]) ans = -1 while q: @@ -141,10 +150,10 @@ class Solution(object): i, j = q.popleft() if (i, j) == target: return ans - for _, _, a, b in dirs: + for a, b in pairwise(dirs): x, y = i + a, j + b - if (x, y) in s: - s.remove((x, y)) + if (x, y) in vis: + vis.remove((x, y)) q.append((x, y)) return -1 ``` @@ -163,37 +172,31 @@ class Solution(object): */ class Solution { - private static final char[] dir = {'U', 'R', 'D', 'L'}; - private static final char[] ndir = {'D', 'L', 'U', 'R'}; - private static final int[] dirs = {-1, 0, 1, 0, -1}; - private static final int N = 1010; - private Set s; private int[] target; + private GridMaster master; + private final int n = 2010; + private final String s = "URDL"; + private final int[] dirs = {-1, 0, 1, 0, -1}; + private final Set vis = new HashSet<>(); public int findShortestPath(GridMaster master) { - target = null; - s = new HashSet<>(); - s.add(0); - dfs(0, 0, master); + this.master = master; + dfs(0, 0); if (target == null) { return -1; } - s.remove(0); + vis.remove(0); Deque q = new ArrayDeque<>(); q.offer(new int[] {0, 0}); - int ans = -1; - while (!q.isEmpty()) { - ++ans; - for (int n = q.size(); n > 0; --n) { - int[] p = q.poll(); - int i = p[0], j = p[1]; - if (target[0] == i && target[1] == j) { + for (int ans = 0; !q.isEmpty(); ++ans) { + for (int m = q.size(); m > 0; --m) { + var p = q.poll(); + if (p[0] == target[0] && p[1] == target[1]) { return ans; } for (int k = 0; k < 4; ++k) { - int x = i + dirs[k], y = j + dirs[k + 1]; - if (s.contains(x * N + y)) { - s.remove(x * N + y); + int x = p[0] + dirs[k], y = p[1] + dirs[k + 1]; + if (vis.remove(x * n + y)) { q.offer(new int[] {x, y}); } } @@ -202,24 +205,92 @@ class Solution { return -1; } - private void dfs(int i, int j, GridMaster master) { + private void dfs(int i, int j) { if (master.isTarget()) { target = new int[] {i, j}; + return; } for (int k = 0; k < 4; ++k) { - char d = dir[k], nd = ndir[k]; int x = i + dirs[k], y = j + dirs[k + 1]; - if (master.canMove(d) && !s.contains(x * N + y)) { - s.add(x * N + y); - master.move(d); - dfs(x, y, master); - master.move(nd); + if (master.canMove(s.charAt(k)) && vis.add(x * n + y)) { + master.move(s.charAt(k)); + dfs(x, y); + master.move(s.charAt((k + 2) % 4)); } } } } ``` +### **C++** + +```cpp +/** + * // This is the GridMaster's API interface. + * // You should not implement it, or speculate about its implementation + * class GridMaster { + * public: + * bool canMove(char direction); + * void move(char direction); + * boolean isTarget(); + * }; + */ + +class Solution { +private: + const int n = 2010; + int dirs[5] = {-1, 0, 1, 0, -1}; + string s = "URDL"; + int target; + unordered_set vis; + +public: + int findShortestPath(GridMaster& master) { + target = n * n; + vis.insert(0); + dfs(0, 0, master); + if (target == n * n) { + return -1; + } + vis.erase(0); + queue> q; + q.emplace(0, 0); + for (int ans = 0; q.size(); ++ans) { + for (int m = q.size(); m; --m) { + auto [i, j] = q.front(); + q.pop(); + if (i * n + j == target) { + return ans; + } + for (int k = 0; k < 4; ++k) { + int x = i + dirs[k], y = j + dirs[k + 1]; + if (vis.count(x * n + y)) { + vis.erase(x * n + y); + q.emplace(x, y); + } + } + } + } + return -1; + } + + void dfs(int i, int j, GridMaster& master) { + if (master.isTarget()) { + target = i * n + j; + } + for (int k = 0; k < 4; ++k) { + int x = i + dirs[k], y = j + dirs[k + 1]; + if (master.canMove(s[k]) && !vis.count(x * n + y)) { + vis.insert(x * n + y); + master.move(s[k]); + dfs(x, y, master); + master.move(s[(k + 2) % 4]); + } + } + } +}; +``` + ### **...** ``` diff --git a/solution/1700-1799/1778.Shortest Path in a Hidden Grid/Solution.cpp b/solution/1700-1799/1778.Shortest Path in a Hidden Grid/Solution.cpp new file mode 100644 index 0000000000000..ea414076852a2 --- /dev/null +++ b/solution/1700-1799/1778.Shortest Path in a Hidden Grid/Solution.cpp @@ -0,0 +1,64 @@ +/** + * // This is the GridMaster's API interface. + * // You should not implement it, or speculate about its implementation + * class GridMaster { + * public: + * bool canMove(char direction); + * void move(char direction); + * boolean isTarget(); + * }; + */ + +class Solution { +private: + const int n = 2010; + int dirs[5] = {-1, 0, 1, 0, -1}; + string s = "URDL"; + int target; + unordered_set vis; + +public: + int findShortestPath(GridMaster& master) { + target = n * n; + vis.insert(0); + dfs(0, 0, master); + if (target == n * n) { + return -1; + } + vis.erase(0); + queue> q; + q.emplace(0, 0); + for (int ans = 0; q.size(); ++ans) { + for (int m = q.size(); m; --m) { + auto [i, j] = q.front(); + q.pop(); + if (i * n + j == target) { + return ans; + } + for (int k = 0; k < 4; ++k) { + int x = i + dirs[k], y = j + dirs[k + 1]; + if (vis.count(x * n + y)) { + vis.erase(x * n + y); + q.emplace(x, y); + } + } + } + } + return -1; + } + + void dfs(int i, int j, GridMaster& master) { + if (master.isTarget()) { + target = i * n + j; + } + for (int k = 0; k < 4; ++k) { + int x = i + dirs[k], y = j + dirs[k + 1]; + if (master.canMove(s[k]) && !vis.count(x * n + y)) { + vis.insert(x * n + y); + master.move(s[k]); + dfs(x, y, master); + master.move(s[(k + 2) % 4]); + } + } + } +}; \ No newline at end of file diff --git a/solution/1700-1799/1778.Shortest Path in a Hidden Grid/Solution.java b/solution/1700-1799/1778.Shortest Path in a Hidden Grid/Solution.java index 5eb3b6be9df6c..9d2568d1e80d9 100644 --- a/solution/1700-1799/1778.Shortest Path in a Hidden Grid/Solution.java +++ b/solution/1700-1799/1778.Shortest Path in a Hidden Grid/Solution.java @@ -1,66 +1,59 @@ -/** - * // This is the GridMaster's API interface. - * // You should not implement it, or speculate about its implementation - * class GridMaster { - * boolean canMove(char direction); - * void move(char direction); - * boolean isTarget(); - * } - */ - -class Solution { - private static final char[] dir = {'U', 'R', 'D', 'L'}; - private static final char[] ndir = {'D', 'L', 'U', 'R'}; - private static final int[] dirs = {-1, 0, 1, 0, -1}; - private static final int N = 1010; - private Set s; - private int[] target; - - public int findShortestPath(GridMaster master) { - target = null; - s = new HashSet<>(); - s.add(0); - dfs(0, 0, master); - if (target == null) { - return -1; - } - s.remove(0); - Deque q = new ArrayDeque<>(); - q.offer(new int[] {0, 0}); - int ans = -1; - while (!q.isEmpty()) { - ++ans; - for (int n = q.size(); n > 0; --n) { - int[] p = q.poll(); - int i = p[0], j = p[1]; - if (target[0] == i && target[1] == j) { - return ans; - } - for (int k = 0; k < 4; ++k) { - int x = i + dirs[k], y = j + dirs[k + 1]; - if (s.contains(x * N + y)) { - s.remove(x * N + y); - q.offer(new int[] {x, y}); - } - } - } - } - return -1; - } - - private void dfs(int i, int j, GridMaster master) { - if (master.isTarget()) { - target = new int[] {i, j}; - } - for (int k = 0; k < 4; ++k) { - char d = dir[k], nd = ndir[k]; - int x = i + dirs[k], y = j + dirs[k + 1]; - if (master.canMove(d) && !s.contains(x * N + y)) { - s.add(x * N + y); - master.move(d); - dfs(x, y, master); - master.move(nd); - } - } - } +/** + * // This is the GridMaster's API interface. + * // You should not implement it, or speculate about its implementation + * class GridMaster { + * boolean canMove(char direction); + * void move(char direction); + * boolean isTarget(); + * } + */ + +class Solution { + private int[] target; + private GridMaster master; + private final int n = 2010; + private final String s = "URDL"; + private final int[] dirs = {-1, 0, 1, 0, -1}; + private final Set vis = new HashSet<>(); + + public int findShortestPath(GridMaster master) { + this.master = master; + dfs(0, 0); + if (target == null) { + return -1; + } + vis.remove(0); + Deque q = new ArrayDeque<>(); + q.offer(new int[] {0, 0}); + for (int ans = 0; !q.isEmpty(); ++ans) { + for (int m = q.size(); m > 0; --m) { + var p = q.poll(); + if (p[0] == target[0] && p[1] == target[1]) { + return ans; + } + for (int k = 0; k < 4; ++k) { + int x = p[0] + dirs[k], y = p[1] + dirs[k + 1]; + if (vis.remove(x * n + y)) { + q.offer(new int[] {x, y}); + } + } + } + } + return -1; + } + + private void dfs(int i, int j) { + if (master.isTarget()) { + target = new int[] {i, j}; + return; + } + for (int k = 0; k < 4; ++k) { + int x = i + dirs[k], y = j + dirs[k + 1]; + if (master.canMove(s.charAt(k)) && vis.add(x * n + y)) { + master.move(s.charAt(k)); + dfs(x, y); + master.move(s.charAt((k + 2) % 4)); + } + } + } } \ No newline at end of file diff --git a/solution/1700-1799/1778.Shortest Path in a Hidden Grid/Solution.py b/solution/1700-1799/1778.Shortest Path in a Hidden Grid/Solution.py index e7e4b037bdb79..0b307b9aafbd7 100644 --- a/solution/1700-1799/1778.Shortest Path in a Hidden Grid/Solution.py +++ b/solution/1700-1799/1778.Shortest Path in a Hidden Grid/Solution.py @@ -1,56 +1,53 @@ -# """ -# This is GridMaster's API interface. -# You should not implement it, or speculate about its implementation -# """ -# class GridMaster(object): -# def canMove(self, direction: str) -> bool: -# -# -# def move(self, direction: str) -> bool: -# -# -# def isTarget(self) -> None: -# -# - - -class Solution(object): - def findShortestPath(self, master: 'GridMaster') -> int: - def dfs(i, j): - nonlocal target - if master.isTarget(): - target = (i, j) - for dir, ndir, a, b in dirs: - x, y = i + a, j + b - if master.canMove(dir) and (x, y) not in s: - s.add((x, y)) - master.move(dir) - dfs(x, y) - master.move(ndir) - - target = None - s = set() - dirs = [ - ['U', 'D', -1, 0], - ['D', 'U', 1, 0], - ['L', 'R', 0, -1], - ['R', 'L', 0, 1], - ] - dfs(0, 0) - if target is None: - return -1 - s.remove((0, 0)) - q = deque([(0, 0)]) - ans = -1 - while q: - ans += 1 - for _ in range(len(q)): - i, j = q.popleft() - if (i, j) == target: - return ans - for _, _, a, b in dirs: - x, y = i + a, j + b - if (x, y) in s: - s.remove((x, y)) - q.append((x, y)) - return -1 +# """ +# This is GridMaster's API interface. +# You should not implement it, or speculate about its implementation +# """ +# class GridMaster(object): +# def canMove(self, direction: str) -> bool: +# +# +# def move(self, direction: str) -> bool: +# +# +# def isTarget(self) -> None: +# +# + + +class Solution(object): + def findShortestPath(self, master: "GridMaster") -> int: + def dfs(i: int, j: int): + if master.isTarget(): + nonlocal target + target = (i, j) + return + for k, c in enumerate(s): + x, y = i + dirs[k], j + dirs[k + 1] + if master.canMove(c) and (x, y) not in vis: + vis.add((x, y)) + master.move(c) + dfs(x, y) + master.move(s[(k + 2) % 4]) + + s = "URDL" + dirs = (-1, 0, 1, 0, -1) + target = None + vis = set() + dfs(0, 0) + if target is None: + return -1 + vis.discard((0, 0)) + q = deque([(0, 0)]) + ans = -1 + while q: + ans += 1 + for _ in range(len(q)): + i, j = q.popleft() + if (i, j) == target: + return ans + for a, b in pairwise(dirs): + x, y = i + a, j + b + if (x, y) in vis: + vis.remove((x, y)) + q.append((x, y)) + return -1