Дате 2Д мрежу величине н*н где свака ћелија представља трошак проласка кроз ту ћелију задатак је пронаћи минимални трошак да се помери из горе лево ћелија до доле десно ћелија. Из дате ћелије можемо да се уселимо 4 правца : лево десно горе доле.
Напомена: Претпоставља се да негативни циклуси трошкова не постоје у улазној матрици.
јава низ бајтова у стринг
Пример:
Улаз: мрежа = {{9 4 9 9}
{6 7 6 4}
{8 3 3 7}
{7 4 9 10}}
Излаз: 43
Објашњење: Путања минималне цене је 9 + 4 + 7 + 3 + 3 + 7 + 10.
приступ:
Идеја је да се користи Дијкстрин алгоритам да пронађе пут минималних трошкова кроз мрежу. Овај приступ третира мрежу као граф где је свака ћелија чвор и алгоритам динамички истражује најисплативију путању до доње десне ћелије тако што увек прво проширује путање са најнижим трошковима.
Приступ корак по корак:
структуре података у Јави
- Користите мин-хеап да увек прво обрадите најјефтинији пут и гурните горњу леву ћелију у њу.
- Иницијализујте матрицу трошкова са максималним вредностима постављајући цену почетне ћелије на њену вредност мреже.
- За сваку ћелију проверите све 4 суседне ћелије
- Ако се пронађе пут са нижим трошковима, ажурирајте цену ћелије и гурните је у хрпу.
- Вратите минималну цену да бисте дошли до доње десне ћелије.
Испод је примена горњег приступа:
C++// C++ program to find minimum Cost Path with // Left Right Bottom and Up moves allowed #include using namespace std; // Function to check if cell is valid. bool isValidCell(int i int j int n) { return i>=0 && i<n && j>=0 && j<n; } int minimumCostPath(vector<vector<int>> &grid) { int n = grid.size(); // Min heap to implement dijkstra priority_queue<vector<int> vector<vector<int>> greater<vector<int>>> pq; // 2d grid to store minimum cost // to reach every cell. vector<vector<int>> cost(n vector<int>(n INT_MAX)); cost[0][0] = grid[0][0]; // Direction vector to move in 4 directions vector<vector<int>> dir = {{-10} {10} {0-1} {01}}; pq.push({grid[0][0] 0 0}); while (!pq.empty()) { vector<int> top = pq.top(); pq.pop(); int c = top[0] i = top[1] j = top[2]; // Check for all 4 neighbouring cells. for (auto d: dir) { int x = i + d[0]; int y = j + d[1]; // If cell is valid and cost to reach this cell // from current cell is less if (isValidCell(x y n) && cost[i][j]+grid[x][y]<cost[x][y]) { // Update cost to reach this cell. cost[x][y] = cost[i][j]+grid[x][y]; // Push the cell into heap. pq.push({cost[x][y] x y}); } } } // Return minimum cost to // reach bottom right cell. return cost[n-1][n-1]; } int main() { vector<vector<int>> grid = {{9499}{6764}{8337}{74910}}; cout << minimumCostPath(grid) << endl; return 0; }
Java // Java program to find minimum Cost Path with // Left Right Bottom and Up moves allowed import java.util.PriorityQueue; import java.util.Arrays; class GfG { // Function to check if cell is valid. static boolean isValidCell(int i int j int n) { return i >= 0 && i < n && j >= 0 && j < n; } static int minimumCostPath(int[][] grid) { int n = grid.length; // Min heap to implement Dijkstra PriorityQueue<int[]> pq = new PriorityQueue<>((a b) -> Integer.compare(a[0] b[0])); // 2D grid to store minimum cost // to reach every cell. int[][] cost = new int[n][n]; for (int[] row : cost) { Arrays.fill(row Integer.MAX_VALUE); } cost[0][0] = grid[0][0]; // Direction vector to move in 4 directions int[][] dir = {{-1 0} {1 0} {0 -1} {0 1}}; pq.offer(new int[]{grid[0][0] 0 0}); while (!pq.isEmpty()) { int[] top = pq.poll(); int c = top[0] i = top[1] j = top[2]; // Check for all 4 neighbouring cells. for (int[] d : dir) { int x = i + d[0]; int y = j + d[1]; // If cell is valid and cost to reach this cell // from current cell is less if (isValidCell(x y n) && cost[i][j] + grid[x][y] < cost[x][y]) { // Update cost to reach this cell. cost[x][y] = cost[i][j] + grid[x][y]; // Push the cell into heap. pq.offer(new int[]{cost[x][y] x y}); } } } // Return minimum cost to // reach bottom right cell. return cost[n - 1][n - 1]; } public static void main(String[] args) { int[][] grid = { {9 4 9 9} {6 7 6 4} {8 3 3 7} {7 4 9 10} }; System.out.println(minimumCostPath(grid)); } }
Python # Python program to find minimum Cost Path with # Left Right Bottom and Up moves allowed import heapq # Function to check if cell is valid. def isValidCell(i j n): return i >= 0 and i < n and j >= 0 and j < n def minimumCostPath(grid): n = len(grid) # Min heap to implement Dijkstra pq = [] # 2D grid to store minimum cost # to reach every cell. cost = [[float('inf')] * n for _ in range(n)] cost[0][0] = grid[0][0] # Direction vector to move in 4 directions dir = [[-1 0] [1 0] [0 -1] [0 1]] heapq.heappush(pq [grid[0][0] 0 0]) while pq: c i j = heapq.heappop(pq) # Check for all 4 neighbouring cells. for d in dir: x y = i + d[0] j + d[1] # If cell is valid and cost to reach this cell # from current cell is less if isValidCell(x y n) and cost[i][j] + grid[x][y] < cost[x][y]: # Update cost to reach this cell. cost[x][y] = cost[i][j] + grid[x][y] # Push the cell into heap. heapq.heappush(pq [cost[x][y] x y]) # Return minimum cost to # reach bottom right cell. return cost[n - 1][n - 1] if __name__ == '__main__': grid = [ [9 4 9 9] [6 7 6 4] [8 3 3 7] [7 4 9 10] ] print(minimumCostPath(grid))
C# // C# program to find minimum Cost Path with // Left Right Bottom and Up moves allowed using System; using System.Collections.Generic; class GfG { // Function to check if cell is valid. static bool isValidCell(int i int j int n) { return i >= 0 && i < n && j >= 0 && j < n; } static int minimumCostPath(int[][] grid) { int n = grid.Length; // Min heap to implement Dijkstra var pq = new SortedSet<(int cost int x int y)>(); // 2D grid to store minimum cost // to reach every cell. int[][] cost = new int[n][]; for (int i = 0; i < n; i++) { cost[i] = new int[n]; Array.Fill(cost[i] int.MaxValue); } cost[0][0] = grid[0][0]; // Direction vector to move in 4 directions int[][] dir = { new int[] {-1 0} new int[] {1 0} new int[] {0 -1} new int[] {0 1} }; pq.Add((grid[0][0] 0 0)); while (pq.Count > 0) { var top = pq.Min; pq.Remove(top); int i = top.x j = top.y; // Check for all 4 neighbouring cells. foreach (var d in dir) { int x = i + d[0]; int y = j + d[1]; // If cell is valid and cost to reach this cell // from current cell is less if (isValidCell(x y n) && cost[i][j] + grid[x][y] < cost[x][y]) { // Update cost to reach this cell. cost[x][y] = cost[i][j] + grid[x][y]; // Push the cell into heap. pq.Add((cost[x][y] x y)); } } } // Return minimum cost to // reach bottom right cell. return cost[n - 1][n - 1]; } static void Main(string[] args) { int[][] grid = new int[][] { new int[] {9 4 9 9} new int[] {6 7 6 4} new int[] {8 3 3 7} new int[] {7 4 9 10} }; Console.WriteLine(minimumCostPath(grid)); } }
JavaScript // JavaScript program to find minimum Cost Path with // Left Right Bottom and Up moves allowed function comparator(a b) { if (a[0] > b[0]) return -1; if (a[0] < b[0]) return 1; return 0; } class PriorityQueue { constructor(compare) { this.heap = []; this.compare = compare; } enqueue(value) { this.heap.push(value); this.bubbleUp(); } bubbleUp() { let index = this.heap.length - 1; while (index > 0) { let element = this.heap[index] parentIndex = Math.floor((index - 1) / 2) parent = this.heap[parentIndex]; if (this.compare(element parent) < 0) break; this.heap[index] = parent; this.heap[parentIndex] = element; index = parentIndex; } } dequeue() { let max = this.heap[0]; let end = this.heap.pop(); if (this.heap.length > 0) { this.heap[0] = end; this.sinkDown(0); } return max; } sinkDown(index) { let left = 2 * index + 1 right = 2 * index + 2 largest = index; if ( left < this.heap.length && this.compare(this.heap[left] this.heap[largest]) > 0 ) { largest = left; } if ( right < this.heap.length && this.compare(this.heap[right] this.heap[largest]) > 0 ) { largest = right; } if (largest !== index) { [this.heap[largest] this.heap[index]] = [ this.heap[index] this.heap[largest] ]; this.sinkDown(largest); } } isEmpty() { return this.heap.length === 0; } } // Function to check if cell is valid. function isValidCell(i j n) { return i >= 0 && i < n && j >= 0 && j < n; } function minimumCostPath(grid) { let n = grid.length; // Min heap to implement Dijkstra const pq = new PriorityQueue(comparator) // 2D grid to store minimum cost // to reach every cell. let cost = Array.from({ length: n } () => Array(n).fill(Infinity)); cost[0][0] = grid[0][0]; // Direction vector to move in 4 directions let dir = [[-1 0] [1 0] [0 -1] [0 1]]; pq.enqueue([grid[0][0] 0 0]); while (!pq.isEmpty()) { let [c i j] = pq.dequeue(); // Check for all 4 neighbouring cells. for (let d of dir) { let x = i + d[0]; let y = j + d[1]; // If cell is valid and cost to reach this cell // from current cell is less if (isValidCell(x y n) && cost[i][j] + grid[x][y] < cost[x][y]) { // Update cost to reach this cell. cost[x][y] = cost[i][j] + grid[x][y]; // Push the cell into heap. pq.enqueue([cost[x][y] x y]); } } } // Return minimum cost to // reach bottom right cell. return cost[n - 1][n - 1]; } let grid = [ [9 4 9 9] [6 7 6 4] [8 3 3 7] [7 4 9 10] ]; console.log(minimumCostPath(grid));
Излаз
43
Временска сложеност: О(н^2 лог(н^2))
Помоћни простор: О(н^2 лог(н^2))
Зашто се динамичко програмирање не може користити?
Динамичко програмирање овде не успева јер омогућавање кретања у сва четири правца ствара циклусе у којима се ћелије могу поново прегледати кршећи претпоставку о оптималној подструктури. То значи да цена доласка до ћелије из дате ћелије није фиксна, већ зависи од целе путање.
Повезани чланци:
Путања минималне цене
Креирај квиз