Admissible Heuristic Modification - algorithm

I am currently working on a project involving a puzzle and various pathfinding algorithms. The puzzle is represented using a 2d array, and has a specific form factor. Each cell in the 2d array has a jump value, and that is the number of spaces you can move up, down, left, or right from the cell.
I am currently working on implementing A* search on this puzzle. I was thinking of using manhattan distance as an admissible heuristic for this problem, but I do not think that the conventional manhattan distance will work since movement is limited to a specific number of moves.
For example:
2 2 2 1 1
1 1 1 2 2
3 1 2 1 1
3 1 2 1 1
2 1 1 1 0
Is a possible grid. You start from the 2 in the top left cell and are trying to get to the 0 in the bottom right cell. From the start cell, you can move right two or down 2 to new spaces which have different jump values. This process repeats until the goal is reached if the puzzle is solvable.
How can I modify the manhattan distance abs(x1-x2) + abs(y1-y2) to incorporate moving a specific number of spaces?

As you have observed Manhattan distance isn't an admissible heuristic, e.g. starting from P = (3,2) you have:
Manhattan(P, Target) = abs(3 - 4) + abs(2 - 4) = 1 + 2 = 3
but the real distance is just 2.
An admissible heuristic is:
h(P) = (P_x != Target_x) + (P_y != Target_y)
where
| 1 if x == y
(x != y) = |
| 0 otherwise
This works since for every component of the current-position-vector that doesn't match the corresponding component in target vector you have to take at least 1 move.

Related

Find out minimum steps to reach any corner of maze?

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!!

Algorithm - How to pair blocks efficiently

lets say, we have two cubes of 3X3 with different heights in cell. Each cell value represents the height of that cell. For example in below block 1, cell (1,1) has height of 1, cell(1,2) has height of 2 and so on.
block-1,
1 2 3
1 3 2
3 1 2
block-2,
4 3 2
4 2 3
2 4 3
Giver two such blocks how to check efficiently whether two blocks can be connected in such a way that there would be no cell mismatched and both blocks together produce a cuboid.
For example, above block-1 + block-2 can be connected and resultant block will be a perfect cuboid height 5. Resultant cuboid will be,
5 5 5
5 5 5
5 5 5
Extension of the problem: Given a set (size >= 50K) of such 4X4 blocks how to connect pair of blocks and produce maximum height sum of resultant cuboid? You can take only matched blocks full height to maximise total height sum. Non matched blocks will be ignored. Each cell height can be up to 20 unit.
Further extension of the problem: Blocks can be given in such a way that might be rotated to make pair with other to maximise resultant cuboids height sum.
Any clue?
You could solve the problem in two steps (1) find all pairs of blocks that connect (build a cuboid) and (2) find the best pairing that maximizes the total height.
Find connecting pairs
For this I would (a) build a surface representation for each block, (b) hash the blocks by their surface representation and (c) search for each block all connecting blocks by looking for the connecting surface models.
(a) Building the surface model
The basic idea is to represent each block by its surface. For this you just subtract the minimum entry in the matrix from every entry in the matrix
surface representation of block-1 will be
1 2 3 -1 0 1 2
1 3 2 --> 0 2 1
3 1 2 2 0 2
and surface representation of block-2 will be
4 3 2 -2 2 1 0
4 2 3 --> 2 0 1
2 4 3 0 2 1
(b) hash the blocks
Now you hash the blocks by their surface representation
(c) Finding connecting pairs
For each block you then compute the connecting surface model, by taking the maximum value in the surface representation and subtracting the entries in the matrix from it,
for block-1 this will yield
0 1 2 2 1 0
2 - 0 2 1 = 2 0 1
2 0 2 0 2 0
the blocks with this surface representation can be found using the hash table (note that the surface representation of block-2 will match).
Note: when you allow for rotation then you will have to perform 4 queries on the hash table with all possible rotations.
Finding the best pairing
To find the best pairing (maximizing the sum of connected blocks) I would use the Hungarian Algorithm. In order to do this you will have to build a matrix where the entry (i, j) contains the height of the block when the two blocks i and j connect and 0 otherwise.
Edit
I think the second step (finding best pairing) can be done more efficiently, by connecting pairs of matching blocks greedily (connecting pairs resulting in highest blocks first).
The intuition for this is: When you have two blocks a and b and they both have the same surface model. Then they will either both connect to another block c or they both won't connect to c. With this in mind, after the "find connecting pairs" step you will end up with pairs of groups of blocks (Xi, Yi) where each block of Xi connects to each block of Yi. If the two groups Xi and Yi are of equal size, then we can connect in any way we want and will always get the same sum of height of resulting cuboids. If one of the groups (wlog Yi) contains less elements then we want to avoid connecting to the smallest blocks in Xi. Thus we can greedily connect starting with the largest blocks and in doing so avoid connecting to the smallest blocks.
So the algorithm could work as follows:
(Hash each block according to its surface representation. Sort
blocks with the same surface representation descending according to
their offset (height of block minus surface representation)
Process blocks in order of descending offset, for each block: Search
for connecting block cBlock with highest offset, connect the two
blocks, remove cBlock from the hash table and the processing
pipeline.
Overall this should be doable in O(n log n)

Algorithm - Finding the most rewarding path in a given graph

Question: You are given the following inputs:
3
0 0 1
3 1 1
6 0 9
The first line is the number of points on the graph.
The rest of the lines contain the points on the graph, and their reward. For example:
0 0 1 would mean at point (0,0) [which is the starting point] you are given a reward of 1.
3 1 1 would mean at point (3,1) you are given a reward of 1.
6 0 9 would mean at point (6, 0) you are given a reward of 9.
Going from point a, to point b costs 1.
Therefore if you go from (0,0) -> (3,1) -> (6,0) your reward is 11-2 (cost of traversing 2 nodes) * sqrt(10).
Goal: Determine the maximum amount of rewards you can make (the total amount of reward you collect - the cost) based on the provided inputs.
How would I go about solving this? It seems like dynamic programming is the way to go, but I am not sure where to start.

Maximum path cost in matrix

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

Find minimum number of rectangles of length 2 in a grid of binary values

Given a grid, I need to "cover" the true values with rectangles. The rectangles can only be horizontal or vertical and they can cover two cells at max.
For example, in this case:
1 1 1 0 0
1 0 0 0 1
0 0 0 1 0
the minimum number of ractangles is 4: 1 from [0][0] to [1][0], 2 from [0][1] to [0][2], 3 with only [1][4] (since there aren't any adjacent 1s in the up, down, left and right directions) and the last one with only [2][3] in it.
I suppose, the problem comes when the grid has many consecutive 1s that split in many directions. For example
1 1 1 1 1
1 0 0 0 0
1 0 0 1 0
1 1 1 1 0
or
1 1 1
1 0 1
1 1 1
I cannot think of a pretty efficient algorithm to solve this problem, a greedy approach seems to be ineffective.
Any help would be really much appreciated, thanks.
EDIT:
The greedy algorithm I've tried: scan the matrix 1 row at a time, if there's a 1 in the current position, then check if there's another 1 in the next row position [rowIndex][columnIndex + 1] and "cover" both with one rectangle. If not, check the cell below the current position [rowIndex + 1][columnIndex] and do as before. If there aren't any 1s in these positions, cover only the current cell. As you can see, this algorithm doesn't work in the first case. Perhaps the algorithm must know all the consecutive 1s to compute the minimum number of rectangles. Because of this, I'm wondering if some graph stuff comes in, but I can't still think of an optimal solution.
I would simply go through the matrix and as soon I see a 1 I try to create a new rectangle with an adjacent 1 which can be on the same line or row and has no other adjacent 1 otherwise the rectangle will cover only the current cell and then you scan the matrix until you find a new uncovered 1 or you have scanned the enteir matrix, in this way you can cover all the 1 with the minumum number of rectangle (if I'm not wrong).
for i=0 to N
for j=0 to M
if (1==matrix[i][j] AND notCovered(i,j)){
k,l=adjacent(i,j)//return an adjacent 1 that cannot be covered, if all the adjacent 1 can be covered return the one on the same row
if (k AND l == VOID )
cover (i,j)
else
cover (i,j)(k,l)
}
Of course you can do some improvement on this algorithm, I hope this will help you

Resources