Project Euler #82: Path sum: three ways
Project Euler #82: Path sum: three ways
+ 0 comments I rotated the matrix so the starting becomes the right side and then used normal dp and in the end calculation i just take the minimum of last column. Sow why is my logic failing. It only passes 2 test cases and wrong answer for others but why?
import sys l=[] for _ in range(int(input())): l.append(list(map(int,input().strip().split(" ")))) n=len(l) cost=[] for i in range(n): cost.append(l[i][::-1]) #print(cost) dp=[[0 for i in range(n)] for j in range(n)] for i in range(n): dp[i][0]=dp[i-1][0]+cost[i][0] for j in range(n): dp[0][j] = dp[0][j-1] + cost[0][j] for i in range(1,n): for j in range(1,n): dp[i][j]=min(dp[i-1][j],dp[i][j-1]) + cost[i][j] #print(dp) minimum=sys.maxsize for i in range(0,n-1): if minimum>dp[i][n-1]: minimum=dp[i][n-1] print(minimum)
+ 0 comments I'm using Dijkstra with a PriorityQueue. It runs fast enough but is failing on tests 3 through 6
<?php function euler082($matrix, $n): int { $graph = graph($matrix, $n); $length = count($graph); $distances = array_fill(0, $length, null); $target = $length - 1; $start = $target - 1; $pq = new MinPq(); $distances[$start] = 0; $pq->insert($start, $distances[$start]); while (!$pq->isEmpty()) { list($curr, $dist) = $pq->extract(); foreach ($graph[$curr] as $next => $next_dist) { $sum = $dist + $next_dist; if (is_null($distances[$next]) || $distances[$next] > $sum) { $distances[$next] = $sum; $pq->insert($next, $distances[$next]); } } } return $distances[$target]; } function graph($matrix, $n) { $length = $n ** 2; $graph = []; $transforms = [ # row, col, index [-1, 0, -$n], [0, -1, -1], [1, 0, $n], [0, 1, 1], ]; // Connecting graph vertexes for ($index = 0; $index < $length; $index++) { list($row, $col) = ydiv($index, $n); foreach ($transforms as list($trow, $tcol, $tidx)) { $trow += $row; $tcol += $col; $tidx += $index; if (isset($matrix[$trow][$tcol])) { $dist = $matrix[$trow][$tcol]; $graph[$index][$tidx] = $dist; } } } // Connecting start and target vertexes to first and last columns $start_index = $length; $target_index = $start_index + 1; for ($row = 0; $row < $n; $row++) { $first_col_idx = $row * $n; $last_col_idx = ($row + 1) * $n - 1; $graph[$start_index][$first_col_idx] = $matrix[$row][0]; $graph[$first_col_idx][$start_index] = 0; $graph[$target_index][$last_col_idx] = $matrix[$row][$n - 1]; $graph[$last_col_idx][$target_index] = 0; } return $graph; } class MinPq extends SplPriorityQueue { public function __construct() { $this->setExtractFlags(self::EXTR_BOTH); } public function extract() { return array_values(parent::extract()); } public function compare($a, $b) { return -($a <=> $b); } } function ydiv(int $a, int $b): array { return [ intval($a / $b), $a % $b, ]; } function gets(): string { return trim(fgets(STDIN)); } function puts(string $str): void { echo $str, PHP_EOL; } function logs($var): void { ob_start(); if (is_scalar($var)) { puts($var); } else { var_dump($var); } error_log(trim(ob_get_clean())); } $n = intval(gets()); for ($i = 0; $i < $n; $i++) { $matrix[$i] = array_map('intval', explode(' ', gets())); } puts(euler082($matrix, $n));
+ 0 comments I used Dijkstra's Algorithm (using heapq (similar to priority queue) of Python), graph is such that there is a source vertex and n^2 other vertices. Edges from source vertex to the vertices of the first column are having weight = grid(i,0) for i=0 to n-1 and all other vertices (i,j) have incoming edges (from left to right, up to down, down to up) with weight=grid(i,j). Then take the minimum dist(i,n-1) for i=0 to n-1.
Works fine in Python 3 but avoid creating a "Graph". Use list not dictionary. dict is very slow. Only for source, adjacent vertices have a condition, for all other vertices, the conditions are same so it can be solved without actually building a graph with adjacency lists and costs.
Even Dijkstra's Algorithm worked in O(n^2) by just adding one extra vertex.
+ 1 comment This is my code it is not working on test case 5 and 6.
#include <bits/stdc++.h> using namespace std; #define ll unsigned long long int #define MAX 1002 struct Cell{ int x, y; ll sum; Cell(){} Cell(int _x, int _y, ll _sum){ x=_x, y=_y, sum=_sum; } }; class compare{ public: bool operator()(Cell a, Cell b){ return a.sum > b.sum; } }; ll pathsum(ll grid[MAX][MAX], int n){ if (n==0) return 0; int visited[MAX][MAX]; memset(visited, 0, sizeof(visited)); priority_queue<Cell, vector<Cell>, compare> que; for (int i=0; i<n; i++){ que.push(Cell(i, 0, grid[i][0])); visited[i][0] = 1; } ll min_sum = INT_MAX; while (!que.empty()){ Cell cell = que.top(); que.pop(); if (cell.y==n-1) { min_sum = min(min_sum, cell.sum); return min_sum; } //down if (cell.x+1>=0 && cell.x+1<n && cell.y>=0 && cell.y<n && visited[cell.x+1][cell.y]==0){ visited[cell.x+1][cell.y]=1; que.push(Cell(cell.x+1, cell.y, cell.sum+grid[cell.x+1][cell.y])); } //right if (cell.x>=0 && cell.x<n && cell.y+1>=0 && cell.y+1<n && visited[cell.x][cell.y+1]==0){ visited[cell.x+1][cell.y]=1; que.push(Cell(cell.x, cell.y+1, cell.sum+grid[cell.x][cell.y+1])); } //up if (cell.x-1>=0 && cell.x-1<n && cell.y>=0 && cell.y<n && visited[cell.x-1][cell.y]==0){ visited[cell.x-1][cell.y]=1; que.push(Cell(cell.x-1, cell.y, cell.sum+grid[cell.x-1][cell.y])); } } return (min_sum==INT_MAX)?-1:min_sum; } int main() { int n; cin >> n; ll grid[MAX][MAX]; for (int i=0; i<n; i++){ for (int j=0; j<n; j++){ cin >> grid[i][j]; } } cout << pathsum(grid, n) << endl; return 0; }
+ 1 comment After finishing Problem 83 with Dijkstra, I came back here to try this problem also with Dijkstra. It is interesting how the difference in the size constraint makes it implausible to construct the graph in advance. Doing so results in Runtime Error in Python for the last 3 test cases, which I suppose is related to the memory-heavy nature of
dict
data type.It is also noticeable that using Dijkstra is not necessarily faster than a naive loop-the-whole-thing-until-nothing-can-be-changed approach.
Sort 13 Discussions, By:
Please Login in order to post a comment