I'm working some programming exercises. This one has been quite well known and answered in different places.
FrogRiverOne
Find the earliest time when a frog can jump to the other side of a river.
https://codility.com/programmers/task/frog_river_one/
My question is, what if the Frog can jump a distance of D? how can we find the shortest time to cross the river, with the best runtime complexity? Thanks!
int solution(int X, vector<int> &A, int D); // frog can jumps from 1 to D steps
I think shole's greedy solution is almost correct. If you include a recursive propagation step when you change Current_Pos, you will ensure that the frog is always at the front-most position.
Here is an alternative that avoids the recursion:
Use an occupancy array that stores for each position if there is a leaf. And use a union-find data structure with nodes for every position. The union-find data structure will keep track of nodes that can be reached from each other (i.e. connected components). The task then is to find the first point in time when both river banks are connected.
To find this, do the following: Every time a new leaf comes into play, mark its position as occupied. Then, unite the node in the union-find data structure with every other occupied node that is reachable from this position (-D to +D). Finally, check if both river banks are connected. Overall time complexity is O(ND+X).
Which of the two solutions is faster depends on the input.
Try this on c# with Linq :
private static int FrogRiverOne(int X,int[] A)
{
if (Enumerable.Range(1,X).Except(A).Any()) { return -1; }
var orderBy = A.Select((y, z) => new { y, z }).GroupBy(a => a.y).Select(a =>
{ var ff = a.Min(xe => xe.z); return new { a,ff }; });
var second = orderBy.Max(xe => xe.ff);
return second;
}
Related
Let's say I have a weighted, undirected, acyclic graph with no negative value weights, comprised of n vertices and n-1 edges. If I want to calculate the total distance between every single one of them (using edge weight) and then add it up, which algorithm should I use? If for example a graph has 4 vertices, connected like a-b, a-c, c-d then the program should output the total distance needed to go from a-d, a-c, a-b, b-c, b-d and so on. You could call it every possible path between the given vertices. The language I am using is C++.
I have tried using Dijikstra's and Prim's algorithm, but none have worked for me. I have thought about using normal or multisource DFS, but I have been struggling with it for some time now. Is there really a fast way to calculate it, or have I misunderstood the problem entirely?
Since you have an acyclic graph, there is only one possible path between any two points. This makes things a lot simpler to compute and you don't need to use any real pathfinding algorithms.
Let's say we have an edge E that connects nodes A and B. Calculate how many nodes can be reached from node A, not using edge E (including A). Multiply that by the number of nodes that can be reached from node B, not using edge E (including B). Now you have the number of paths that travel through edge E. Multiply this by the weight of edge E, and you have the total contribution of edge E to the sum.
Do the same thing for every edge and add up the results.
To make the algorithm more efficient, each edge can store cached values that say the number of nodes that are reachable on each side of the edge.
You don't have to use a depth first search. Here is some pseudocode showing how you calculate the number of nodes reachable on a side of edge E very fast taking advantage of caching:
int count_nodes_reachable_on_edge_side(Edge e, Node a) {
// assume edge e directly connects to node a
if (answer is already cached in e) { return the answer; }
answer = 1; // a is reachable
for each edge f connected to node a {
if (f is not e) {
let b be other node f touches (not a)
answer += count_nodes_reachable_on_edge_side(f, b)
}
}
cache the answer in edge e;
return answer;
}
I already presented an O(N^2) algorithm in my other answer, but I think you can actually do this in O(N) time with this pseudo code:
let root be an arbitrary node on the graph;
let total_count be the total number of nodes;
let total_cost be 0;
process(root, null);
// Returns the number of nodes reachable from node n without going
// through edge p. Also adds to total_cost the contribution from
// all edges touching node n, except for edge p.
int process(Node n, Edge p)
{
count = 1
for each edge q that touches node n {
if (q != p) {
let m be the other node connected to q (not n)
sub_count = process(m, q)
total_cost += weight(q) * sub_count * (total_count - sub_count)
count += sub_count
}
}
return count
}
The run time of this is O(N), where N is the number of nodes, because process will be called exactly once for each node.
(For the detail-oriented readers: the loop inside process does not matter: there are O(N) iterations that call process, because process is called on each node exactly once. There are O(N) iterations that don't do anything (because q == p), because those iterations can only happen once for process call.)
Every edge will also be visited. After we recursively count the number of nodes on one side of the edge, we can do a simple subtraction (total_count - sub_count) to get the number of nodes on the other side of the edge. When we have these two node counts, we can just multiply them together to get the total number of paths going through the edge, then mulitply that by the weight, and add it to the total cost.
I am solving this question on LeetCode.com called Path With Minimum Effort:
You are given heights, a 2D array of size rows x columns, where heights[row][col] represents the height of cell (row, col). Aim is to go from top left to bottom right. You can move up, down, left, or right, and you wish to find a route that requires the minimum effort. A route's effort is the maximum absolute difference in heights between two consecutive cells of the route. Return the minimum effort required to travel from the top-left cell to the bottom-right cell. For e.g., if heights = [[1,2,2],[3,8,2],[5,3,5]], the answer is 2 (in green).
The code I have is:
class Solution {
public:
vector<pair<int,int>> getNeighbors(vector<vector<int>>& h, int r, int c) {
vector<pair<int,int>> n;
if(r+1<h.size()) n.push_back({r+1,c});
if(c+1<h[0].size()) n.push_back({r,c+1});
if(r-1>=0) n.push_back({r-1,c});
if(c-1>=0) n.push_back({r,c-1});
return n;
}
int minimumEffortPath(vector<vector<int>>& heights) {
int rows=heights.size(), cols=heights[0].size();
using arr=array<int, 3>;
priority_queue<arr, vector<arr>, greater<arr>> pq;
vector<vector<int>> dist(rows, vector<int>(cols, INT_MAX));
pq.push({0,0,0}); //r,c,weight
dist[0][0]=0;
//Dijkstra
while(pq.size()) {
auto [r,c,wt]=pq.top();
pq.pop();
if(wt>dist[r][c]) continue;
vector<pair<int,int>> neighbors=getNeighbors(heights, r, c);
for(auto n: neighbors) {
int u=n.first, v=n.second;
int curr_cost=abs(heights[u][v]-heights[r][c]);
if(dist[u][v]>max(curr_cost,wt)) {
dist[u][v]=max(curr_cost,wt);
pq.push({u,v,dist[u][v]});
}
}
}
return dist[rows-1][cols-1];
}
};
This gets accepted, but I have two questions:
a. Since we update dist[u][v] if it is greater than max(curr_cost,wt), how does it guarantee that in the end we return the minimum effort required? That is, why don't we end up returning the effort of the one in red above?
b. Some solutions such as this one, short-circuit and return immediately when we reach the bottom right the first time (ie, if(r==rows-1 and c==cols-1) return wt;) - how does this work? Can't we possibly get a shorter dist when we revisit the bottom right node in future?
The problem statement requires that we find the path with the minimum "effort".
And "effort" is defined as the maximum difference in heights between adjacent cells on a path.
The expression max(curr_cost, wt) takes care of the maximum part of the problem statement. When moving from one cell to another, the distance to the new cell is either the same as the distance to the old cell, or it's the difference in heights, whichever is greater. Hence max(difference_in_heights, distance_to_old_cell).
And Dijkstra's algorithm takes care of the minimum part of the problem statement, where instead of using a distance from the start node, we're using the "effort" needed to get from the start node to any given node. Dijkstra's attempts to minimize the distance, and hence it minimizes the effort.
Dijkstra's has two closely related concepts: visited and explored. A node is visited when any incoming edge is used to arrive at the node. A node is explored when its outgoing edges are used to visit its neighbors. The key design feature of Dijkstra's is that after a node has been explored, additional visits to that node will never improve the distance to that node. That's the reason for the priority queue. The priority queue guarantees that the node being explored has the smallest distance of any unexplored nodes.
In the sample grid, the red path will be explored before the green path because the red path has effort 1 until the last move, whereas the green path has effort 2. So the red path will set the distance to the bottom right cell to 3, i.e. dist[2][2] = 3.
But when the green path is explored, and we arrive at the 3 at row=2, col=1, we have
dist[2][2] = 3
curr_cost=2
wt=2
So dist[2][2] > max(curr_cost, wt), and dist[2][2] gets reduced to 2.
The answers to the questions:
a. The red path does set the bottom right cell to a distance of 3, temporarily. But the result of the red path is discarded in favor of the result from the green path. This is the natural result of Dijkstra's algorithm searching for the minimum.
b. When the bottom right node is ready to be explored, i.e. it's at the head of the priority queue, then it has the best distance it will ever have, so the algorithm can stop at that point. This is also a natural result of Dijkstra's algorithm. The priority queue guarantees that after a node has been explored, no later visit to that node will reduce its distance.
Problem :
Think about cars in a race as points on a line. All the cars start at
the same point with an initial speed of zero. All of them move in
the same direction. There are N cars in total, numbered from 1 to
N.
You will be given two kinds of queries :
1. Change the speed of the car i at any time t
2. Output the current winner of the race at any time t
For query type 1, I will be given the time, Car No. and the New Speed.
For query type 2, I will be given the time at which the we need to find the winning car.
Constraints :
N <= 50,000 , Queries <= 10^5
Also time in every query would be >= time in the previous query
What I tried till now :
#include<bits/stdc++.h>
using namespace std;
pair<int,pair<int,int> > arr[50005];//this stores car's last position,speed,time(at which this speed was assigned)
int main()
{
int n,q;
cin>>n>>q;
for(int i=1;i<=n;++i){arr[i]={0,{0,0}};}
while(q--)
{
int type;
cin>>type;
if(type==1)
{
int time,car,speed;
cin>>time>>car>>speed;
arr[car].first= arr[car].first + 1LL*(time-arr[car].second.second)*arr[car].second.first;// new position
arr[car].second.first = speed;
arr[car].second.second = time;
}
else
{
int ans=-1,time;
cin>>time;
for(int i=1;i<=n;++i){
//position at the "time" is the last position plus distance travelled
int temp = (time - arr[i].second.second)*arr[i].second.first + arr[i].first;
// farthest car is the current winner
ans = max(ans,temp);
}
cout<<ans<<endl;
}
}
return 0;
}
Since this approach answers the type 2 query in O(N) it is really ineffecient.
Since I only need an update operation and max range query I thought of using segment tree to speed this up to O(LogN).
I actually was halfway through my code when i realised that it isn't possible to answer query type 2 with this ! What i stored was essentially the same with an extra variable winning_car ! I thought for type 1 query I would just update the variables the same way i did above but for answering which car is winning at the moment I couldn't come up with a query function that would answer that in O(LogN). Either it is possible to write such a function ( which i am not able to) or i stored insufficient information in my node( I think it is this) !
What should I store in the tree node ? (or is it not possible with segment tree ?). Not asking for a ready-made code here, just the approach(if it is complex some pseudo-code would be nice though)
Yesterday I tested my program of landscape evolution with a big data set(20 Million nodes), without a doubt the running speed was unacceptable. During debugging I noticed that it was a certain function which slowed the whole system down. So I'd like to add multithreading process to it.
However, the function itself is a nested loop with pointer iterators and I believe some of the data has to be locked during the process.
Basically what I was trying to do is to calculate the contributing area of each node. Contributing area, as suggested by its name, is a product (sum) of of all area from upstream node.
Here is the code of that two functions,
for( curnode = nodIter.FirstP(); nodIter.IsActive();
curnode = nodIter.NextP() ) //iterating thru a linked-list of pointers to active stream nodes (*IsActive* returns a bool value)
{
CalcDRArea( curnode, curnode->getVArea() ); //calls another function and pass a pointer to current node as well as a value of its VArea
}
void CalcDRArea( NodeClass *curnode, double addedArea )
{
// As long as the current node is neither a boundary nor non-valid, add
// _addedArea_ to its total drainage area and advance to the next node downstream
while( (curnode->ReachBoundary() == NonBoundary) &&
(curnode->valid()!=Nonvalid) )
{
curnode->AddDrArea( addedArea ); //*AddDrArea* is a simple inline function *`"drarea +=value"`*
curnode = curnode->getDownStreammNeighbor(); // *getDownstrmNbr()* reruns a pointer to the downstream node
}
}
Here is a simple illustration of nodes and their flowing direction
A B C D
\ | / |
E F G H
| |
I Q K L
| /
M N O P
//letters are stream nodes and slashes are their flowing directions
My plan is to use OpenMP to implement multithreading at the beginning of first function, the for loop. Ideally it will create several threads to calculate each node separately.
However, as shown in figure above, a sequent process can handle streams like
A-> F -> Q -> N
B-> F -> Q -> N
C-> F -> Q -> N
easily, but it will definitely cause problem in a multithreading conditions.
From what I've just read from OpenMP's document, flush and lock might be the right way to do this, but still I am quite clueless right now and there might still be other potential issues within this loops (like gcc ver. of OpenMP doesn't support "!=").
====Update ======
There are two kinds of areas: vArea, which is the area of each node; and drArea which is the sum of the area of current node and area from all its upstream nodes.
I was wondering if I can change the current function to this :
for( active node iterator)
{
if(currentNode.hasDownStreamNode)
{
downStreamNode.drArea += currentNode.vArea + currentNode.DrArea;
}
CurrentNode.drArea += currentNode.varea;
}
Before worrying about parallelism, you should first pick a better algorithm. Although in this case one actually goes with the other.
You want a dynamic programming solution in O(N) instead of your current O(n^2) approach. The intuition is simple, just call the following method on each of the leaf nodes in your tree:
def compute_value(node):
if node.DrArea != 0: return node.DrArea
total = node.vArea
for n in node.upstream_nodes():
total += compute_value(n)
node.DrArea = total
return node.DrArea
To see why this is more efficient, let's take a look at your example. At the moment you add the value of A to F, Q and N. Then you do the same for B and for C. So you have 12 add operations.
The recursive method on the other hand computes the value for A, B and C first, then we compute F from the already known values of A, B and C. Q gets computed from F and so on. So that's only 8 adds. Basically every node only adds its total value to all of its children instead of going through the whole subtree and adding only its own value.
For a simple sequential algorithm you can then go ahead and just implement this iteratively using a list of nodes whose predecessors have all been evaluated (so instead of starting from leaves start from the root nodes). The easiest parallel implementation here is to just use a concurrent queue and atomic add operations, although using one normal queue per processor and some work-stealing would probably be a very good idea in practice.
I have searched Google and Stackoverflow for this question, but I still don't understand how a minimax function works.
I found the wikipedia entry has a pseudocode version of the function:
function integer minimax(node, depth)
if node is a terminal node or depth <= 0:
return the heuristic value of node
α = -∞
for child in node: # evaluation is identical for both players
α = max(α, -minimax(child, depth-1))
return α
Several other minimax functions I found with Google are basically the same thing; I'm trying to implement this in C++, and this is what I have come up with so far:
double miniMax(Board eval, int iterations)
{
//I evaluate the board from both players' point of view and subtract the difference
if(iterations == 0)
return boardEval(eval, playerNumber) - boardEval(eval, opponentSide());
/*Here, playerTurn tells the findPossibleMoves function whose turn it is;
I mean, how do you generate a list of possible moves if you don't even know
whose turn it's supposed to be? But the problem is, I don't see where I can
get playerTurn from, as there are only 2 parameters in all the examples of
minimax I've seen*/
vector<int> moves = eval.findPossibleMoves(playerTurn);
//I'm assuming -∞ in the wikipedia article means a very low number?
int result = -999999999;
//Now I run this loop to evaluate each possible move
/*Also, the Lua example in the wiki article has
alpha = node.player==1 and math.max(alpha,score) or math.min(alpha,score)
Is alpha a boolean there?!*/
for(int i = 0; i * 2 < moves.size(); i++)
{
//I make a copy of the board...
Board temp = eval;
/*and make the next possible move... once again playerTurn crops up, and I
don't know where I can get that variable from*/
temp.putPiece(moves[i * 2], moves[i * 2 + 1], playerTurn);
/*So do I create a function max that returns the bigger of two doubles?*/
result = max(result, -miniMax(temp, iterations - 1));
}
return result;
/*So now I've returned the maximum score from all possible moves within a certain
# of moves; so how do I know which move to make? I have the score; how do I know
which sequence of moves that score belongs to?*/
}
As you can see, I'm pretty confused about this minimax function. Please at the very least give me some hints to help me with this.
Thanks! :)
That sample from Wikipedia is doing NegaMax with Alpha/Beta pruning.
You may be helped by getting the naming straight:
The basis is MiniMax, a literal implementation would involve 2 methods that take turns (mutually recursive), 1 for each side.
Lazy programmers turn this into NegaMax, one method with a strategically placed - operator.
Alpha/Beta pruning is keeping track of a Window of best moves (over multiple depths) to detect dead branches.
Your playerTurn is used to determine whose turn it is . In NegaMax you can derive this from the depth (iterations) being odd or even. But it would be easier to use 2 parameters (myColor, otherColor) and switch them at each level.
Your miniMax() function should remember the best move it found so far. So instead of this code:
/*So do I create a function max that returns the bigger of two doubles?*/
result = max(result, -miniMax(temp, iterations - 1));
You should do something like this:
/*So do I create a function max that returns the bigger of two doubles?*/
double score = -miniMax(temp, iterations - 1);
if (score > result)
{
result = score;
bestMove = i;
}
Of course, you need a variable "bestMove" and a way to return the best move found to the caller.
Add the playerTurn variable as an argument to miniMax, and call miniMax which the current player's move initially and recursively.
Also, opponentSide needs to be a function of playerTurn.
A good place to start with game tree searching is the chess programming wiki. For your question about the move: I think it is most common to have two max-functions. The difference between the two max functions is that one returns only the score and the other returns the score and the best move. A recursive call order would be like following:
maxWithBestMoveReturn(...) --> min(...) --> max(...) --> min(...)
There are some good papers with pseudocode for the Alpha Beta algorithm:
TA Marsland - Computer Chess and Search
J Schaeffer - The games Computers (and People) Play
To your question in the comment: and math.max(alpha,score) or math.min(alpha,score) Is alpha a boolean there?!
No alpha is a window bound in a alpha beta algorithm. The alpha value gets updated with a new value. Because alpha and beta are swapped with the recursive call of the negamax-Function the alpha variable refers to the beta variable in the next recursive call.
One note to the playerTurn variable: The minimax or alpha-beta algorithm doesn't need this information. So i would give the information -- who's next --, into the Board-Structure. The functions findPossibleMoves and boardEval get all information they need from the Board-Structure.
One note to the recursive break condition: If i understand your code right, then you only have the one with iterations == o. I think this means the algorithm has reached the desired depth. But what if there are no possible moves left befor the algorithm reaches this depth. Maybe you should write following:
vector<int> moves = findPossibleMoves(...);
if (!moves.size())
return boardEval(...);
In your pseudocode, the node variable has to contain all the information about the current board position (or whatever). This information would include whose turn it is to move.