I am working on a project where I need to solve a maze using the minimum number of right turns and no left turns.
The distance travelled is irrelevant as long as right turns are minimized. We are asked to implement our program using both a backtracking algorithm and an optimal (time) one.
For the backtracking algorithm I was going use a stack. My algorithm would be something like:
Push all four possible starting directions on the stack.
Follow a path, going straight whenever possible.
If we reach the end of the maze return the current path length as the best.
If we reach a dead end backtrack to the last possible right turn and take it.
If the current path length is greater than the current best, backtrack to the last possible right turn and take it.
I was wondering if anyone could point me in the direction of an optimal algorithm for this.
I'm having a tough time thinking of anything better than the backtracking one.
I think you can do it by first finding all the points that are reachable with 0 right turns. Then with just 1 right turn, and so on. You can use a queue for doing that. Note that in the n-th phase you've got optimal solutions for all the points that can be reached with n right turns. More so - any not yet reached point is reachable with > n points or not reachable at all. In order to achieve optimal time complexity you have to use the fact that you need to search for new reachable points only from those reached points, which have an unreached neighbour in the appropriate direction. As every point has only 4 neighbours you will only search from it 4 times. You can implement it by maintaining a separate list for every direction D containing all the reached points with an unreached neighbour in that direction. This gives you a time complexity proportional to the area of the maze that is proportional to the size of your input data.
Below I present a graphical example:
. . . . . . (0) . . . . . 0 1 1 1 1 (1) 0 1 1 1 1 1
. ####### . . 0 ########## . 0 ########## . 0 ########## 2
. # . # . . 0 # . # . . 0 # . # . . 0 # . # . (2)
. # . . . . 0 # . . . . 0 # . . . . 0 # . . . (2)
. #### . # . 0 #### . # . 0 #### . # . 0 #### . # 2
(.) . . . . . (0) . . . . . 0 1 1 1 1 1 0 1 1 1 1 1
0 1 1 1 1 1 0 1 1 1 1 1
0 ########## 2 0 ########## 2
0 # . # 3 2 0 # 4 # 3 2
0 # (3) 3 3 2 0 # 3 3 3 2
0 #### . # 2 0 #### 4 # 2
0 1 1 (1) 1 1 0 1 1 1 1 1
( ) denote reached points with the appropriate neighbour unreached
Build a graph by constructing four nodes for every position in the maze. Every node will correspond to a particular direction: N, S, E, W.
There will be edges between every node and at most three of its adjacent neighbors: the ones to the "front", "back" and "right" (if they exist). The edge leading to the node in the "front" and "back" will have weight 0 (since the path length doesn't matter), whereas the edge to the node in the "right" will have weight 1 (this is what represents the cost of making a right turn).
Once the graph is set up (and probably the best way to do this is to reuse the original representation of the maze) a modified variant of the breadth-first search algorithm will solve the problem.
The trick to handle the 0/1 edge weights is to use a deque instead of the standard queue implementation. Specifically, nodes reached through 0 weight edges will be pushed in the front of the deque and the ones reached through edges of weight 1 will be pushed in the back.
Related
The purpose of this post is mainly for keywords for related researches.
Unconstrained N-Rook Problem
Count all possible arrangements of N rooks on an N by M (N<=M) chessboard so that no rooks are attacking each other.
The solution is trivial: C(M,N)N!
Constrained N-Rook Problem
You cannot put a rook at certain places of the chessboard.
For example, if the chessboard is presented as a 0-1 matrix, where 0 are the places you cannot put a rook at. So the solution for the matrix
1 1 1
1 1 1
0 1 1
is 4:
R . . | R . . | . R . | . . R
. R . | . . R | R . . | R . .
. . R | . R . | . . R | . R .
Related Problem
A backtracking algorithm can be easily modified from N-Queen problem. However, now I want to solve a problem for around N=28. This solution is too huge to count 1 by 1, even wiki said
The 27×27 board is the highest-order board that has been completely enumerated.
Chances to Speed Up
There are a few chances I thought of so far to speed up the algorithm.
=====Factorial for Unconstrained Submatrix=====
This is a Divide and Conquer method. e.g. The matrix above
1 1 1
1 1 1
0 1 1
can be divided as
A B
1 1 1 | 0 1 1
1 1 1 |
and the solution is equal to sol(A)*sol(B), where sol(A)=2! which can be calculated at once (factorial is much faster than backtracking).
=============Rearrangement=============
Sometimes rearrangement can help to divide the subproblem. e.g. The matrix
1 1 1
1 0 1
1 1 1
is equivalent to
1 1 1
1 1 1
0 1 1
Question
What is the keyword for this kind of problem?
Are there any efficient developed technique for this kind of problem?
The rook polynomial, rook coefficient, restricted permutations and permanent are the keywords.
From Theorem 3.1 of Algorithm for Finding the Coefficients of Rook Polynomials
The number of arrangements of n objects with restriction board B is equal to permanent of B.
Here B is what we defined in the question, a 0-1 matrix where 1 is ok, 0 is restricted for a rook.
So now we need to efficiently calculate the permanent of a matrix.
Fortunately, from this code golf, Ton Hospel uses Glynn formula with a Gray code and Ryser formula, and reach about 57 seconds on the tester's system for n=36, which is quite enough for the questioner's case.
You have given a n*m maze (matrix) which contains values 0, 1 and 2 . value 0 means cell is open , value 1 means cell is block and value 2 is starting point. You can go only in left ,right ,top ,down direction in maze. Find out minimum distance from starting point to any corner of matrix .
Example :
n = 4, m = 5
maze :
1 1 1 0 1 1 0 2 0 1 1 0 1 0 1 0 0 1 0 1
Answer will be 2 .
path -> starting point(2 ,3)->(2,4)->(1,4).
Help me to solve this problem !!
If you are familiar with BFS and already solved the following classic problem:
Calculate the shortest path from a starting point to ending point in 2D
grid with some obstacles!
then you can solve your problem by running BFS from starting point once and then going through all corner points having value 0 and comparing the minimum distance among them.
There can be several paths leading to minimum distance. If you want to trace the path then you can maintain another 2D grid for storing parent's information of each 2D point while performing BFS.
Please let me know if you face any problem while coding. Thanks!!
Can anyone tell the algorithm for finding the maximum path cost in a NxM matrix starting from top left corner and ending with bottom right corner with left ,right , down movement is allowed in a matrix and contains negative cost. A cell can be visited any number of times and after visiting a cell its cost is replaced with 0
Constraints
1 <= nxm <= 4x10^6
INPUT
4 5
1 2 3 -1 -2
-5 -8 -1 2 -150
1 2 3 -250 100
1 1 1 1 20
OUTPUT
37
Explanation is given in the image
Explanation of Output
Since you have also negative costs then use bellman-ford. What you do is that you change sign of all the costs(convert negative signs to positive and positive to negative) then find the shortest path and this path will be the longest because you have changed the signs.
If the sign is never becoms negative then use dijkstra shrtest-path but before that make all values negative and this will return you the longest path with it's cost.
You matrix is a direct graph. In your image you are trying to find a path(max or min) from index (0,0) to (n-1,n-1).
You need these things to represent it as a graph.
You need a linkedlist and in each node you have a first_Node, second_Node,Cost to move from first node to second.
An array of linkedlist. In each array index you save a linkedlist.If for example there is a path from 0 to 5 and 0 to 1(it's an undirected graph) then your graph will look like this.
If you want a direct-graph then simply add in adj[0] = 5 and do not add in adj[5] = 0 , this means that there is path from 0 to 5 but not from 5 to zero.
Here linkedlist represents only nodes which are connected not there cost. You have to add extra variable there which keep cost for each two nodes and it will look like this.
Now instead of first linkedlist put this linkedlist in your array and you have a graph now to run shortest or longest path algorithm.
If you want an intellgent algorithm then you can use A* with heuristic, i guess manhattan will be best.
If cost of your edges is not negative then use Dijkstra.
If cost is negative then use bellman-ford algorithm.
You can always find the longest path by converting the minus sign to plus and plus to minus and then run shortest path algorithm. Path founded will be longest.
I answered this question and as you said in comments to look at point two. If that's a task then main idea of this assignment is ensure the Monotonocity.
h stands for heuristic cost.
A stands for accumulated cost.
Which says that each node the h(A) =< h(A) + A(A,B). Means if you want to move from A to B then cost should not be decreasing(can you do something with your values such that this property will hold) but increasing and once you satisfy this condition then everyone node which A* chooses , that node will be part of your path from source to Goal because this is the path with shortest/longest value.
pathMax You can enforece monotonicity. If there is path from A to B such that f(S...AB) < f(S ..B) then set cost of the f(S...AB) = Max(f(S...AB) , f(S...A)) where S means source.
Since moving up is not allowed, paths always look like a set of horizontal intervals that share at least 1 position (for the down move). Answers can be characterized as, say
struct Answer {
int layer[N][2]; // layer[i][0] and [i][1] represent interval start&end
// with 0 <= layer[i][0] <= layer[i][1] < M
// layer[0][0] = 0, layer[N][1] = M-1
// and non-empty intersection of layers i and i+1
};
An alternative encoding is to note only layer widths and offsets to each other; but you would still have to make sure that the last layer includes the exit cell.
Assuming that you have a maxLayer routine that finds the highest-scoring interval in each layer (const O(M) per layer), and that all such such layers overlap, this would yield an O(N+M) optimal answer. However, it may be necessary to expand intervals to ensure that overlap occurs; and there may be multiple highest-scoring intervals in a given layer. At this point I would model the problem as a directed graph:
each layer has one node per score-maximizing horizontal continuous interval.
nodes from one layer are connected to nodes in the next layer according to the cost of expanding both intervals to achieve at least 1 overlap. If they already overlap, the cost is 0. Edge costs will always be zero or negative (otherwise, either source or target intervals could have scored higher by growing bigger). Add the (expanded) source-node interval value to the connection cost to get an "edge weight".
You can then run Dijkstra on this graph (negate edge weights so that the "longest path" is returned) to find the optimal path. Even better, since all paths pass once and only once through each layer, you only need to keep track of the best route to each node, and only need to build nodes and edges for the layer you are working on.
Implementation details ahead
to calculate maxLayer in O(M), use Kadane's Algorithm, modified to return all maximal intervals instead of only the first. Where the linked algorithm discards an interval and starts anew, you would instead keep a copy of that contender to use later.
given the sample input, the maximal intervals would look like this:
[0]
1 2 3 -1 -2 [1 2 3]
-5 -8 -1 2 -150 => [2]
1 2 3 -250 100 [1 2 3] [100]
1 1 1 1 20 [1 1 1 1 20]
[0]
given those intervals, they would yield the following graph:
(0)
| =>0
(+6)
\ -1=>5
\
(+2)
=>7/ \ -150=>-143
/ \
(+7) (+100)
=>12 \ / =>-43
\ /
(+24)
| =>37
(0)
when two edges incide on a single node (row 1 1 1 1 20), carry forward only the highest incoming value.
For each element in a row, find the maximum cost that can be obtained if we move horizontally across the row, given that we go through that element.
Eg. For the row
1 2 3 -1 -2
The maximum cost for each element obtained if we move horizontally given that we pass through that element will be
6 6 6 5 3
Explanation:
for element 3: we can move backwards horizontally touching 1 and 2. we will not move horizontally forward as the values -1 and -2, reduces the cost value.
So the maximum cost for 3 = 1 + 2 + 3 = 6
The maximum cost matrix for each of elements in a row if we move horizontally, for the input you have given in the description will be
6 6 6 5 3
-5 -7 1 2 -148
6 6 6 -144 100
24 24 24 24 24
Since we can move vertically from one row to the below row, update the maximum cost for each element as follows:
cost[i][j] = cost[i][j] + cost[i-1][j]
So the final cost matrix will be :
6 6 6 5 3
1 -1 7 7 -145
7 5 13 -137 -45
31 29 37 -113 -21
Maximum value in the last row of the above matrix will be give you the required output i.e 37
I have simple graph and I need to find heuristic costs for this graph.
Graph is (matrix representation):
0 1 2 0 0 0 0
1 0 0 3 3 2 0
3 0 0 2 0 0 0
0 3 1 0 1 0 0
0 3 0 1 0 6 0
0 2 0 0 6 0 2
0 0 0 0 0 2 0
Image:
Values in brackets means heuristic costs of the vertex for current goal vertex.
Green vertex is start and red vertex is goal.
I created this heristic costs matrix:
0 2 6 3 1 9 5
9 0 2 4 6 4 1
1 3 0 5 2 9 4
3 1 5 0 1 7 8
0 6 2 1 0 10 14
2 1 6 3 7 0 5
1 4 3 2 1 3 0
I have to explain this. This matrix represents this: for example goal vertex is 7; we find 7th row in matrix; value in 1st col means heuristic cost from 1 vertex to 7 vertex (7 is goal); value in 5nd col means heurisitc cost from 5 vertex to 7 vertex (7 is goal); if 5 is goal, we will work with 5 row, etc...
This heusristic costs based on nothing. I don't know how to find good heuristic costs. That is the question.
To summarize:
Firstly, my algorithm found wrong path (because of wrong heuristics probably). It found 1-3-4-5 (length 5), but best is 1-2-5 (length 4).
Also, teacher said, that my heuristic costs prevents the algorithm to find good path, but not helps him. I have problems with translating what he said into english, but he said somethink like: "your heuristic mustn't overestimate best path". What does it mean?
So the question: how to find good heuristic costs in my case?
I am going to wrap my comments as an answer.
First, note that "overestimate best path" means that your shortest path from some node v to the goal is of length k, but h(v)=k' such that k'>k. In this case, the heuristic is overestimating the length of the path. A heuristic that does it for 1 or more nodes is called "inadmissible", and A* is not guaranteed to find the shortest path with such a heuristic.
An admissible heuristic function (never overestimating) is guaranteed to provide the optimal path for A*.
The simplest admissible heuristic is h(v) = 0 for all v. Note that in this case, A* will actually behave like Dijsktra's Algorithm (which is basically an uniformed A*).
You can find more informative heuristics, one example is to first pre-process the graph and find the shortest unweighted path from each node to the goal. This can be done efficiently by BFS. Denote this unweighted distance from some v to the goal as uwd(v).
Now, you can create a heuristic which is uwd(v) * MIN_WEIGHT, where MIN_WEIGHT is the smallest edge weight in the graph.
a grid of NxN is given. each point is assigned a value say num
starting from 1,1 we have to traverse to N,N.
if i,j is current position we can go right or down.
How to find the min sum of digits by traversing from 1,1 to n,n along any path
any two points can have same number
ex
1 2 3
4 5 6
7 8 9
1+2+3+6+9 = 21
n <=10000000000
Output 21
Can someone explain how to approach the problem?
This is a dynamic programming problem. The subproblem here is the minimum cost/path to get to any given square. Because you can only move down and to the right, there are only two squares that can let you enter a given square, the one above and the one to the left. Therefore the cost of getting to a square (i,i) is min(cost[i-1][i], cost[i][i-1]) + num. If this would put you out of bounds, only consider the option that is inside the grid. Calculate each row from left to right, doing the top row first and working your way down. The cost you get at (N,N) will be the minimal cost.
Here is my solution with dynamic - programming in O(n^2)
you start with (1,1) so you can find say a = (1,2) and b = (2,1) by a = value(1,1) + value(1,2). Then, to find (2,2) select the minimum (a+ value(2,2)) and (b + value(2,2)) and continue with this logic. You can find any minimum sum among (1,1) and (i,j) with that algorithm. Let me explain,
Given Matrix
1 2 3
4 5 6
7 8 9
Shortest path :
1 3 .
5 . .
. . .
so to find (2,2) take the original value(2,2)=5 from Given Matrix and select min(5 + 5), 3 + 5) = 8. so
Shortest path :
1 3 6
5 8 .
12 . .
so to find (3,2) select min (12 + 8, 8 + 8) = 16 and (2,3) = min(8 + 6, 6 + 6) = 12
Shortest path :
1 3 6
5 8 12
12 16 .
so the last one (3,3) = min (12 + 9, 16 + 9) = 21
Shortest path :
from (1,1) to any point (i, j)
1 3 6
5 8 12
12 16 21
You can convert the grid into a graph. The edges get the weights of the values from your grid elements. Then you can find the solution with the shortest path problem.
start--1--+--2--+--3--+
| | |
4 5 6
| | |
+--5--+--6--+
| | |
7 8 9
| | |
+--8--+--9--end
Can someone explain how to approach the problem?
Read about dynamic programming and go from there.
Attempt:
Start with the first row and calculate the cumulative values and store them.
Proceed to the second row, now the values could have only come from the left or top (since you can only go left or down), calculate the smallest of the cumulative values for this row.
Iterate down the rows until the last and you'll be able to get the smallest value when you reach the last node.
I claim this algorithm is O(n) since if you use a 2 dimensional array you only need to access all fields at most twice (read from top, left) for read and once for write.
If you want to go really fancy or have to operate on massive matrices, A* could also be an option.