There is a 2-d grid which contains chocolates in random cells.In one move ,i can take all the chocolates contained in one row or in one column.What will be the minimum number of moves required to take all the chocolates?
Example:cells containing chocolates are:
0 0
1 1
2 2
min. no of moves =3
0 0
1 0
0 1
min no of moves=2
I guess there is a greedy algo solution to this problem.But how to approach this problem?
I think this is a variance of classic Set Cover problem which is proved to be NP-hard.
Therefore, a greedy algorithm could only get an approximation but not the optimal solution.
For this specific problem, it is not NP-hard. It can be solved in polynomial time. The solution is as below:
Transform the 2D grid to be a bipartite graph. The left side contains nodes represent row and the right side contains nodes represent column. For each cell containing chocolate, suppose it's coordinate is (x,y), add an edge linking row_x and column_y. After the bipartite graph is established, use Hungarian algorithm to get the maximum matching. Since in bipartite graph, the answer of maximum matching equals minimum vertex covering, the answer is exactly what you want.
The Hungarian algorithm is a O(V*E) algorithm. For more details, pls refer to Hungarian algorithm
For more information about bipartite graph, pls refer to Bipartite graph, you can find why maximum matching equals minimum vertex covering here.
PS: It's neither a greedy problem nor dynamic programming problem. It is a graph problem.
Related
I have a rectangular grid shaped DAG where the horizontal edges always point right and the vertical edges always point down. The edges have positive costs associated with them. Because of the rectangular format, the nodes are being referred to using zero-based row/column. Here's an example graph:
Now, I want to perform a search. The starting vertex will always be in the left column (column with index 0) and in the upper half of the graph. This means I'll pick the start to be either (0,0), (1,0), (2,0), (3,0) or (4,0). The goal vertex is always in the right column (column with index 6) and "corresponds" to the start vertex:
start vertex (0,0) corresponds to goal vertex (5,6)
start vertex (1,0) corresponds to goal vertex (6,6)
start vertex (2,0) corresponds to goal vertex (7,6)
start vertex (3,0) corresponds to goal vertex (8,6)
start vertex (4,0) corresponds to goal vertex (9,6)
I only mention this to demonstrate that the goal vertex will always be reachable. It's possibly not very important to my actual question.
What I want to know is what search algorithm should I use to find the path from start to goal? I am using C++ and have access to the Boost Graph Library.
For those interested, I'm trying to implement Fuchs' suggestions from his Optimal Surface Reconstruction from Planar Contours paper.
I looked at A* but to be honest didn't understand it and wasn't how the heuristic works or even whether I could come up with one!
Because of the rectangular shape and regular edge directions, I figured there might be a well-suited algorithm. I considered Dijkstra
but the paper I mention said there were quicker algorithms (but annoyingly for me doesn't provide an implementation), plus that's
single-source and I think I want single-pair.
So, this is your problem,
DAG no cycles
weights > 0
Left weight < Right weight
You can use a simple exhaustive search defining every possible route. So you have a O(NxN) algoririthm. And then you will choose the shortest path. It is not a very smart solution, but it is effective.
But I suppose you want to be smarter than that, let's consider that if a particular node can be reached from two nodes, you can find the minimum of the weights at the two nodes plus the cost for arriving to the current node. You can consider this as an extension of the previous exhaustive search.
Remember that a DAG can be drawn in a line. For DAG linearization here's an interesting resource.
Now you have just defined a recursive algorithm.
MinimumPath(A,B) = MinimumPath(MinimumPath(A,C)+MinimumPath(A,D)+,MinimumPath(...)+MinimumPath(...))
Of course the starting point of recursion is
MinimumPath(Source,Source)
which is 0 of course.
As far as I know, there isn't an out of the box algorithm from boost to do this. But this is quite straightforward to implement it.
A good implementation is here.
If, for some reason, you do not have a DAG, Dijkstra's or Bellman-Ford should be used.
if I'm not mistaken, from the explanation this is really an optimal path problem not a search problem since the goal is known. In optimization I don't think you can avoid doing an exhaustive search if you want the optimal path and not an approximate path.
From the paper it seems like you are really subdividing a space many times then running the algorithm. This would reduce your N to closer to a constant in the context of the entire surface making O(N^2) not so bad.
That being said perhaps dynamic programming would be a good strategy where the N would be bounded by the difference between your start and goal node. Here is an example form genomic alignment. Just an illustration to give you an idea of how it works.
Construct a N by N array of cost values all set to 0 or some default.
#
For i in size N:
For j in size N:
#cost of getting here from i-1 or j-1
cost[i,j] = min(cost[i-1,j] + i edge cost , cost[i,j-1] + j edge cost)
Once you have your table filled in, start at bottom right corner. Starting from your goal, Choose to go to the node with the lowest cost of getting there. Work your way backwards choosing the lowest value until you reach the start node (or rather the array entry corresponding to the start node). This should give you the optimal path very simply.
Dynamic programming works by solving the optimization on smaller sub-problems. In this case the sub-problems are optimal paths to preceding nodes. I think the rectangular nature of your graph makes this a good fit.
First, this is a homework question. I have a boolean matrix where 1s represent nodes, and adjacent nodes are considered connected.
for example:
1 0 0 0 1
1 1 1 0 0
1 0 0 1 1
0 0 0 0 0
0 0 0 0 0
This matrix contains 3 groups by the definition I've been given. One in the top left, consisting of 5 nodes, one in the top right consisting of 1 node, and one below that consisting of 2 nodes.
What I need to do is write a function(s) that determines the fewest number of nodes that must be added to the matrix in order to connect all of the separate components. Two groups are connected when a path can be made from any node in one group to the other.
So, what I'm asking is for someone to shove me in the right direction in terms of algorithms. I've considered how I might use path finding algorithms to find the shortest path between two groups, but am unsure of how I could do this for every group in the matrix. If I use a depth first traversal to determine the separate groups, could I then use a path finding algorithm for any arbitrary node within each group to another?
The generic problem is called the Steiner Tree problem, and it is NP-complete.
There is an algorithm that's not exponential, but gives you a suboptimal solution.
The way you can do it is to compute shortest paths between any two pair of components, do the minimum spanning tree on using just the initial components and the weights you computed, then go through you solution and eliminate cycles.
Since you have a bunch of options for connecting islands I would add a step to optimize the connections.
But an algorithm for the optimal answer: NP-complete (try every combination).
Consider every connected component(group) as a node. Then you can run MST (Minimum Spanning Tree) algorithm to find the min cost to connect all the groups.
Complexity: Complexity to build the edges = O(M*M) + O(ElgV) (M is the number of 1's on the the given grid and M*M operations to find Manhattan distance every pair of 1's to find the Manhattan distance of every pair of groups) and O(ElgV) is the complexity of finding MST
I have 32 segments of the overlapped regions of two images. I have to assign each of the segment to either one of the images based on lowest cost. So, it is a binary labeling problem, and above are the energy minimization function.
L is the vector of length of 32(equal to the number of segments) and value of each element depends on its index corresponding to the segment number. Say, if 3rd segment is assigned image 1, then L(2)=0, and 14th segments is assigned to image 2, so L(13)=1. That is L[x]'s value is either 0 or 1. Thus, there are 2^32 possible assignment of L. So, I can compute E(L) for each combination, after performing 2^32 calculation, I can get the minimum E(L), and use that combination. This is what my intuition suggests. But this is impractical, because the complexity is exponential.
But, many literatures suggest this binary labeling problem can be solved as a graph cut problem with max flow/min cut algorithm. But, how do I formulate this problem as max flow/min cut problem? The 32 segments are the nodes of the graph, but what would be the weight of the edges? And what would be the capacity?
The formulation as a graph theory problem and proof of the "if and only if" relationship can be found in "What Energy Functions Can Be Minimized
via Graph Cuts?" by Vladimir Kolmogorov and Ramin Zabih.
The key idea is to construct a directed edge between i and j of weight Vij(0,1)+Vij(1,0)-Vij(0,0)-Vij(1,1).
If Vij(1,0)-Vij(0,0)>0 you also need to construct a directed edge between the source and i of weight Vij(1,0)-Vij(0,0).
Otherwise you need to construct a directed edge between i and the destination of weight Vij(0,0)-Vij(1,0).
Similarly, if Vij(0,1)-Vij(0,0)>0 you also need to construct a directed edge between the source and j of weight Vij(0,1)-Vij(0,0).
Otherwise you need to construct a directed edge between j and the destination of weight Vij(0,0)-Vij(0,1).
Note that the min-cut of this graph will be offset by V(0,0)-sum of weights on edges connecting to the destination.
I need to compare many graphs(up to a few millions graph comparisons) and I wonder what is the fastest way to do that.
Graphs' vertices can have up to 8 neighbours/edges and vertex can have value 0 or 1. Rotated graph is still the same graph and every graph has identical number of vertices.
Graph can look like this:
Right now I'm comparing graphs by taking one vertex from first graph and comparing it with every vertex from second graph. If I find identical vertex then I check if both vertices' neighbours are identical and I repeat this until I know if graphs are identical or not.
This approach is too slow. Without discarding graphs that are for sure different, it takes more than 40 seconds to compare several thousands graphs with about one hundred vertices.
I was thinking about calculating unique value for every graph and then only compare values. I tried to do this, but I only managed to come up with values that if are equal then graphs may be equal and if values are different then graphs are different too.
If my program compares these values, then it calculates everything in about 2.5 second(which is still too slow).
And what is the best/fastest way to add vertex to this graph and update edges? Right now I'm storing this graph in std::map< COORD, Vertex > because I think searching for vertex is easier/faster that way.
COORD is vertex position on game board(vertices' positions are irrelevant in comparing graphs) and Vertex is:
struct Vertex
{
Player player; // Player is enum, FIRST = 0, SECOND = 1
Vertex* neighbours[8];
};
And this graph is representing current board state of Gomoku with wrapping at board edges and board size n*n where n can be up to 2^16.
I hope I didn't made too many errors while writing this. I hope someone can help me.
First you need to get each graph into a consistent representation, the natural way to do this is to create an ordered representation of the graph.
The first level of ordering is achieved by grouping according to the number of neighbours.
Each group of nodes with the same number of neighbours is then sorted by mapping their neighbours values (which are 0 and 1) on a binary number which is then used to enforce an order amongst the group nodes.
Then you can use a hashing function which iterates over each node of each group in the ordered form. The hashed value can then be used to provide an accelerated lookup
The problem you're trying to solve is called graph isomorphism.
The problem is in NP (although it is not known whether it's NP-Complete) and no polynomial time algorithm for it has been found.
The algorithm you describe seems to take exponential time.
This is a possible suggestion for optimization.
I would recommend to try memoization (store all the vertex pairs that are found to be different), so that the next time those two vertices are compared you just do a simple lookup and reply. This may improve the performance (or worsen it), depending on the type of graphs you have.
You have found out yourself that checking isomorphism can be done by checking one bord with all the n*n shifts times 8 rotations of the other, thus having O(n^3) complexity.
This can be reduced to O(n^2). Let's shift only in one direction, say by moving the x axis. Then we only have to find the proper y-offset. For this, we concatenate the elements as follows for both graphs:
. . 1 . 0 . . 3
0 1 . . => 0 1 2 . => 0 3 0 1 2 0 2
. 0 . . 0 . 2 .
_______
1 2 3 4 ^---- a 0 indicates start of a row
We get two arrays of size n and we have to check whether one is a cyclic permutation of the other. For this, we concatenate array a with itself and search for the other.
For example if the two arrays would be a=0301202 and b=0203012 we search for 0203012 in 03012020301202 using KMP or similar, which runs in O(n + 2n)=O(n) time (we can get rid of the whole preprocessing since the first array always is the same).
Combining this O(n) x-check with the n y-shifts and the 8 rotations gives O(n^2) overall complexity by using O(n) additional space.
I have a question. Is there an efficient way to get the Hamiltonian paths between two nodes in a grid graph, leaving some predefined nodes out?
eg. (4*3 grid)
1 0 0 0
0 0 0 0
0 0 2 3
finding a Hamiltonian paths in this grid b/w vertices 1 and 2, but not covering 3? It seems bipartite graphs are a way, but what according to you must be the most efficient way. The problem itself is NP complete.
Delete the nodes you dont need to include and run the brute force algorithm to find Hamiltonian path. This will take O((n-h)!+n), which is NP, where h is the number of nodes deleted, but that is the best you can do. Also to find Hamiltonian path, there is a dynamic approach but that too is exponential( O(2^n*n^2))
There's no need to leave those predefined nodes out: just consider them visited and you can still work your graph as a rectangular grid graph. I'd recommend a bitset or bitvector representation for the grid if efficiency is important.
When the grid is this small, 4x3, a brute force approach is the fastest. Dynamic programming makes it actually slower unless you have a bigger graph (6x7+). You can also use heuristics to prune your search tree, but again, the graph has to be bigger before it helps.