Minimum jumps to reach end when some points are blocked - algorithm

A person is currently at (0,0) and wants to reach (X,0) and he has to jump a few steps to reach his house.From a point say (a,0), he can jump to either (a + k1,0) i.e forward of k1 steps or he can jump(a-k2,0) i.e backward jump of k2 steps. The first jump he takes must be forward.Also,he cannot jump backward twice consecutively.But he can jump any no of continuous forward jump.There are n points a1,a2 upto an where he cannot jump.
I have to determine minimum no of jumps to reach his house or to conclude that he cannot reach his house. If he can reach house print yes and specify no. of jumps If not print no.
Here
X = location of persons house.
N = no. of points where he cannot jump.
k1 = forward jump.
k2 = backward jump.
example
For inputs
X=6 N=2 k1=4 k2=2
Blocked points = 3 5
the answer is 3 (4 to 8 to 6 or 4 to 2 to 6)
For input
6 2 5 2
1 3
the person cannot reach his house
N can be upto 10^4 and X can be upto 10^5
I thought of using dynamic programming but i'm not able to implement it. Can anyone help?

I think your direction of using dynamic programming can work but I will show another way to solve the question with the same asymptotic time complexity as dynamic programming would achieve.
This question can be described as a problem in graphs where you have X nodes indexed 1 to X and these is an edge between every a and a + k1, b and b - k2, where you remove the nodes in N.
This will be enough if you can jump backward how many times you would like but you cannot jump twice in a row so you can add the following modification: Duplicate the graph's nodes, duplicate also the forward going edges but make them go from the duplicated to the original, now make all of the backward going edges to go to the duplicated graph. Now every backward edge will send you to the duplicated and you will not be able to take a backward edge again until you will go to the original using a forward going edge. This will make sure that after a backward edge you will always take a forward edge - so you will not be able to jump forward twice.
Now finding the shortest path from 1 to X is like finding smallest number of jumps since edge is a jump.
Finding the shortest path in directed unweighted graph takes O(|V|+|E|) time and memory (using BFS), your graph has 2 * X as |V| and also the number of edges will be 2 * 2 * X so time and memory complexity of O(X).
If you can jump backward twice you use the networkx library in python for a simple demo (you can also use if for complicated demo):
import matplotlib.pyplot as plt
import networkx as nx
X = 6
N = 2
k1 = 4
k2 = 2
nodes = [0, 1, 2, 4, 6]
G = nx.DiGraph()
G.add_nodes_from(nodes)
for n in nodes:
if n + k1 in nodes:
G.add_edge(n, n + k1)
if n - k2 in nodes:
G.add_edge(n, n - k2)
nx.draw(G, with_labels=True, font_weight='bold')
plt.plot()
plt.show()
path = nx.shortest_path(G, 0, X)
print(f"Number of jumps: {len(path) - 1}. path: {str(path)}")

Would a breadth-first search be efficient enough?
Something like this? (Python code)
from collections import deque
def f(x, k1, k2, blocked):
queue = deque([(k1, 0, None, None)])
while (queue):
(p, depth, direction, prev) = queue.popleft()
if p in blocked or (x + k2 < p < x - k1): # not sure about these boundaries ... ideas welcome
continue
if p == x:
return depth
blocked.add(p) # visited
queue.append((p + k1, depth + 1, "left", direction))
if prev != "right":
queue.append((p - k2, depth + 1, "right", direction))
X = 6
k1 = 4
k2 = 2
blocked = set([3, 5])
print f(X, k1, k2, blocked)
X = 2
k1 = 3
k2 = 4
blocked = set()
print f(X, k1, k2, blocked)

Here is the code of גלעדברקן in c++:
#include <iostream>
#include <queue>
using namespace std;
struct node {
int id;
int depth;
int direction; // 1 is left, 0 is right
};
int BFS(int start, int end, int k1, int k2, bool blocked[], int length)
{
queue<node> q;
blocked[0] = true;
q.push({start, 0, 0});
while(!q.empty())
{
node f = q.front();
q.pop();
if (f.id == end) {
return f.depth;
}
if(f.id + k1 < length and !blocked[f.id + k1])
{
blocked[f.id + k1] = true;
q.push({f.id + k1, f.depth + 1, 0});
}
if (f.direction != 1) { // If you just went left - don't go left again
if(f.id - k2 >= 0 and !blocked[f.id - k2])
{
blocked[f.id - k2] = true;
q.push({f.id - k2, f.depth + 1, 1});
}
}
}
return -1;
}
int main() {
bool blocked[] = {false, false, false, false, false, false, false};
std::cout << BFS(0, 6, 4, 2, blocked, 7) << std::endl;
return 0;
}
You can control on the length of the steps, the start and end, and the blocked nodes.

Related

Satisfying triples in graph

I'm solving a problem where you have N events (1 <= N <= 100000) over M days (2 <= M <= 10^9). You are trying to find the minimum time of occurrence for each event.
For each event, you know that it couldn't have occurred prior to a day Si. You also have C triples (1 <= C <= 10^5) described by (a, b, x). An event b must have occurred at least x days after a.
Example:
There are 4 events, spread over 10 days. Event 1 had to occur on Day 1 or after. Event 2 had to occur on Day 2 or after. Event 3 had to occur on Day 3 or after. Event 4 had to occur on Day 4 or after.
The triples are (1, 2, 5); (2, 4, 2); (3, 4, 4). This means that Event 2 had to occur at least 5 days after Event 1; Event 4 had to occur at least 2 days after Event 2; and Event 4 had to occur at least 4 days after Event 3.
The solution is that Event 1 occurred on Day 1; Event 2 occurred on Day 6; Event 3 occurred on Day 3; and Event 4 occurred on Day 4. The reasoning behind this is Event 2 occurred at least five days after Event 1, so it cannot have occurred before Day 1+5=6. Event 4 occurred at least two days after Event 2, so it cannot have occurred before Day 6+2=8.
My solution:
I had the idea to use the triples to create a Directed graph. So in the example above, the graph would look like this:
1 --5-> 2 --2-> 4
3 --4-> 4
Basically you create a directed edge from the Event that happened first to the Event that had to happen after. The edge weight would be the number of days it had to at least happen after.
I thought that we could would first use the input data to create the graph. Then, you would just Binary search on all possible starting dates of the first event (1 through 10^9, which is about 30). In this case, the first event is Event 1. Then, you would go through the graph and see if this starting date was possible. If you ever encountered an event where the date it was occurring was before its Si date, then you would terminate this search and continue binary searching. This solution would have worked easy if it wasn't for the "event b must have occurred AT LEAST x days after a".
Does anyone have any other solutions for solving this problem, or how to alter mine so that it works? Thank you! If you have any questions please let me know :))
This can be mapped to a Simple Temporal Network where literature is rich, e.g.:
Dechter, Rina, Itay Meiri, and Judea Pearl. "Temporal constraint networks." Artificial intelligence 49.1-3 (1991): 61-95..
Planken, Léon Robert. "Algorithms for simple temporal reasoning." (2013). full dissertation
As indicated in the comments, all-pairs shortest-paths can calculate the minimal-network (which also generates new arcs/constraints between all these events). If your graph is sparse, Johnson's algorithm is better than Floyd-Warshall.
If you don't care about the complete minimal-network, but only about the bounds of your events, you are only interested in the first column and the first row of the all-pairs shortest-paths distance matrix. You can calculate these values by applying Bellman-Ford *2*n* times. These values are the distances of root -> i and i -> root where root is time 0.
Just some remarks about things which Damien indicated (reasoning from scratch it seems: impressive):
we use negative weights in the general problem such that pure Dijkstra won't do
existance of negative cycle <-> infeasibility / no solution / inconsistent
there will be a need for some root vertex which is the origin of time
Edit: Above somewhat targets strong inference / propagation like giving tight bounds in regards to their value-domains.
If you are only interested in some consistent solution, it might be another idea just to post these constraints as linear-program and use one of the highly-optimized implementations to solve it (open-source world: CoinOR clp; maybe google's glop). Simplex-based ones should give you an integral solution (i think the problem is totally unimodular). Interior-point based solvers should be faster, but i'm not sure if your result will be integral without some additional need for cross-over. (might be a good idea to add some dummy-objective like min(max(x)) (makespan-like))
Consider a topological sort of your DAG.
For a list L corresponding to the toposort of your graph, you have at the end the leaves.
Then for a vertex just before
L = [..., v, leaves]
you know that the edges outoing from v can only go to the vertices after (here the leaves).
This allows you to compute the minimal weight associated to v by applying Damien's max.
Do so up to the head of L.
Topological sorting is O(V+E)
Here is an illustration with a more interesting graph (read it from top to bottom)
5
/ \
4 7
1 2
0
6
A topo ordering is (4601275)
So we will visit in order 4,6,0,1,2,7 then 5 and any vertex we visit has all its dependencies already computed.
Assume each vertex k has event occuring after 2^k days. The after date is referred as weight.
e.g vertex 4 is weighted 2^4
Assume each edge (i,j) is weighted 5*i + j
6 is weighted 2^6 = 64
0 is weighted max(2^0, 64 + (0*5+6)) = 70
1 takes max(2^1, 70 + 5) = 75
7 takes max(2^7, 75 + 5*7+1, 2^2) = 2^7
Point to be highlighted (here for 7) is that the minimal date induced by dependencies of a node may occur before the date attached to that node. (and we have to keep the biggest one)
function topologicalSort({ V, E }) {
const visited = new Set ()
const stack = []
function dfs (v) {
if (visited.has(v)) { return }
E.has(v) && E.get(v).forEach(({ to, w }) => dfs(to))
visited.add(v)
stack.push(v)
}
// process nodes without incoming edges first
const heads = new Set ([...V])
for (const v of V) {
const edges = E.get(v)
edges && edges.forEach(({ to }) => heads.delete(to))
}
for (const v of heads) {
dfs(v)
}
for (const v of V) {
dfs(v)
}
return stack
}
class G {
constructor () {
this.V = new Set()
this.E = new Map()
}
setEdges (from, tos) {
this.V.add(from)
tos.forEach(({ to, w }) => this.V.add(to))
this.E.set(from, tos)
}
}
function solve ({ g, vToWeight }) {
const stack = topologicalSort(g)
console.log('ordering', stack.join(''))
stack.forEach(v => {
const edges = g.E.get(v)
if (!edges) { return }
const newval = Math.max(
vToWeight.get(v),
...edges.map(({ to, w }) => vToWeight.get(to) + w)
)
console.log('setting best for', v, edges.map(({ to, w }) => [vToWeight.get(to), w].join('+') ))
vToWeight.set(v, newval)
})
return vToWeight
}
function demo () {
const g = new G ()
g.setEdges(2, [{ to: 1, w: 5 }])
g.setEdges(4, [{ to: 2, w: 2 }, { to: 3, w: 4 }])
const vToWeight = new Map ([
[1, 1],
[2, 6],
[3, 3],
[4, 4]
])
return { g, vToWeight }
}
function demo2 () {
const g = new G ()
const addEdges = (i, ...tos) => {
g.setEdges(i, tos.map(to => ({ to, w: 5 * i + to })))
}
addEdges(5,4,7)
addEdges(7,1,2)
addEdges(1,0)
addEdges(0,6)
const vToWeight = new Map ([...g.V].map(v => [v, 2**v]))
return { g, vToWeight }
}
function dump (map) {
return [...map].map(([k, v])=> k+'->'+v)
}
console.log('----op\s sol----\n',dump(solve(demo())))
console.log('----that case---\n',dump(solve(demo2())))
The distance matrix (between all pairs of events = nodes) can by obtained in a iterative way, similar to the Floyd algorithm. Basically, iteratively:
T(x, y) = max (T(x,y), T(x, z) +T (z, y))
However, as mentioned by the OP in a comment, Floyd algorithm is O(n^3), which is too much for a value of n up to 10^5.
A key point is that no loop exists, and therefore a more efficient algorithm should exist.
A nice proposal was made by grodzi in their proposal: use a topologic sort of the Directed Acyclic Graph (DAG).
I made an implementation in C++ according to this idea, with on main difference:
I used a simple sort (from C++ library) for building the topological sorting. Doing it is simple and has a complexity of O(n logn). The dedicated method proposed by grodzi could be more efficient (seems O(n)). However, it is very easy to implement and such a complexity remains low.
After the topological sorting, we know that a given event only depends on the events before it. For this part, this insures a complexity of O(C), where C is the number of triples, i.e. the number of edges.
#include <iostream>
#include <vector>
#include <set>
#include <unordered_set>
#include <algorithm>
#include <tuple>
#include <numeric>
struct Triple {
int event1;
int event2;
int days;
};
struct Pred {
int pred;
int days;
};
void print_result (const std::vector<int> &index, const std::vector<int> &times) {
int n = times.size();
for (int i = 0; i < n; i++) {
std::cout << index[i]+1 << " " << times[index[i]] << "\n";
}
}
std::tuple<std::vector<int>, std::vector<int>> ordering (int n, const std::vector<Triple> &triples) {
std::vector<int> index(n);
std::vector<int> times(n, 0);
std::iota(index.begin(), index.end(), 0);
// Build predecessors matrix and sets
std::vector<std::vector<Pred>> pred (n);
std::vector<std::unordered_set<int>> set_pred (n);
for (auto &triple: triples) {
pred[triple.event2 - 1].emplace_back(Pred{triple.event1 - 1, triple.days});
set_pred[triple.event2 - 1].insert(triple.event1 - 1);
}
// Topological sort
std::sort (index.begin(), index.end(), [&set_pred] (int &i, int &j) {return set_pred[j].find(i) != set_pred[j].end();});
// Iterative calculation of times of arrival
for (int i = 1; i < n; ++i) {
int ip = index[i];
for (auto &p: pred[ip]) {
times[ip] = std::max(times[ip], times[p.pred] + p.days);
}
}
// Final sort, according to times of arrival
std::sort (index.begin(), index.end(), [&times] (int &i, int &j) {return times[i] < times[j];});
return {index, times};
}
int main() {
int n_events = 4;
std::vector<Triple> triples = {
{1, 2, 5},
{1, 3, 1},
{3, 2, 6},
{3, 4, 1}
};
std::vector<int> index(n_events);
std::vector<int> times(n_events);
std::tie (index, times) = ordering (n_events, triples);
print_result (index, times);
}
Result:
1 0
3 1
4 2
2 7

Man move from source to destination with constraints

Consider this cartesian graph where each index represents a weight.
[3, 2, 1, 4, 2
1, 3, 3, 2, 2
S, 3, 4, 1, D
3, 1, 2, 4, 3
4, 2, 3, 1, 4]
A man is standing at source 'S' and he has to reach destination 'D' at minimum cost. Constraints are:
If the man moves from one index to another index where both index share same cost, the cost of moving man is '1'.
If the man moves from one index to another index where both indexes have different cost, the cost of moving man is abs(n-m)*10 + 1.
Last but not the least, man can only move up, down, left & right. No diagonal moves.
Which data structure & algorithm is best suited for this problem. I have thought of representing this problem as a graph and use one of the greedy approaches but could not reach to clean solution in my mind.
I would use A* to solve the problem. The distance can be estimated by dx + dy + 10 * dValue + distance travelled (it is impossible that the way is shorter than that, see example at the bottom). The idea of A* is to expand always the node with the lowest estimated distance, as soon as you find the destination node you are finished. This works if the estimation never over-estimates the distance. Here is an implementation in JS (fiddle):
function solve(matrix, sRow, sCol, eRow, eCol) {
if (sRow == eRow && sCol == eCol)
return 0;
let n = matrix.length, m = matrix[0].length;
let d = [], dirs = [[-1, 0], [0, 1], [1, 0], [0, -1]];
for (let i = 0; i < n; i++) {
d.push([]);
for (let j = 0; j < m; j++)
d[i].push(1000000000);
}
let list = [[sRow, sCol, 0]];
d[sRow][sCol] = 0;
for (;;) {
let pos = list.pop();
for (let i = 0; i < dirs.length; i++) {
let r = pos[0] + dirs[i][0], c = pos[1] + dirs[i][1];
if (r >= 0 && r < n && c >= 0 && c < m) {
let v = d[pos[0]][pos[1]] + 1 + 10 * Math.abs(matrix[pos[0]][pos[1]] - matrix[r][c]);
if (r == eRow && c == eCol)
return v;
if (v < d[r][c]) {
d[r][c] = v;
list.push([r, c, v + Math.abs(r - eRow) + Math.abs(c - eCol) + 10 * Math.abs(matrix[r][c] - matrix[eRow][eCol])]);
}
}
}
list.sort(function(a, b) {
if (a[2] > b[2])
return -1;
if (a[2] < b[2])
return 1;
return 0;
});
}
}
The answer for the example is 46 and only 8 nodes are getting expanded!
Estimation example, from (0,0) to D:
distance from S to (0,0) is 22
dx = abs(0 - 4) = 4
dy = abs(0 - 2) = 2
dValue = abs(3 - 1) = 2
estimation = distance + dx + dy + 10 * dValue = 22 + 4 + 2 + 10 * 2 = 48
Note: the implementation uses rows and columns insted of x and y, so they are swapped, it doesn't really matter it just has to be consistent.
Although not explicitly stated, in the problem formulation there seem to be only positive node weights, which means that a shortest path will have no repetition of nodes. As the cost does not depend on the nodes only, approaches like the Bellman-Ford algorithm or the algorithm by Dijkstra are not suitable.
That being said, apparently the path can be found recursively by using depth-first search, where nodes which are currently occuring in the stack may not be visited. Every time the destination is reached, the current path (which is contained in the stack at each time the destination is reached) along with its associated cost, which could be maintained in an auxiliary variable, could be evaluated against the best previously found path. On termination, a path with minimum cost would be stored.

Find final square in matrix walking like a spiral

Given the matrix A x A and a number of movements N.
And walking like a spiral:
right while possible, then
down while possible, then
left while possible, then
up while possible, repeat until got N.
Image with example (A = 8; N = 36)
In this example case, the final square is (4; 7).
My question is: Is it possible to use a generic formula to solve this?
Yes, it is possible to calculate the answer.
To do so, it will help to split up the problem into three parts.
(Note: I start counting at zero to simplify the math. This means that you'll have to add 1 to some parts of the answer. For instance, my answer to A = 8, N = 36 would be the final square (3; 6), which has the label 35.)
(Another note: this answer is quite similar to Nyavro's answer, except that I avoid the recursion here.)
In the first part, you calculate the labels on the diagonal:
(0; 0) has label 0.
(1; 1) has label 4*(A-1). The cycle can be evenly split into four parts (with your labels: 1..7, 8..14, 15..21, 22..27).
(2; 2) has label 4*(A-1) + 4*(A-3). After taking one cycle around the A x A matrix, your next cycle will be around a (A - 2) x (A - 2) matrix.
And so on. There are plenty of ways to now figure out the general rule for (K; K) (when 0 < K < A/2). I'll just pick the one that's easiest to show:
4*(A-1) + 4*(A-3) + 4*(A-5) + ... + 4*(A-(2*K-1)) =
4*A*K - 4*(1 + 3 + 5 + ... + (2*K-1)) =
4*A*K - 4*(K + (0 + 2 + 4 + ... + (2*K-2))) =
4*A*K - 4*(K + 2*(0 + 1 + 2 + ... + (K-1))) =
4*A*K - 4*(K + 2*(K*(K-1)/2)) =
4*A*K - 4*(K + K*(K-1)) =
4*A*K - 4*(K + K*K - K) =
4*A*K - 4*K*K =
4*(A-K)*K
(Note: check that 4*(A-K)*K = 28 when A = 8 and K = 1. Compare this to the label at (2; 2) in your example.)
Now that we know what labels are on the diagonal, we can figure out how many layers (say K) we have to remove from our A x A matrix so that the final square is on the edge. If we do this, then answering our question
What are the coordinates (X; Y) when I take N steps in a A x A matrix?
can be done by calculating this K and instead solve the question
What are the coordinates (X - K; Y - K) when I take N - 4*(A-K)*K steps in a (A - 2*K) x (A - 2*K) matrix?
To do this, we should find the largest integer K such that K < A/2 and 4*(A-K)*K <= N.
The solution to this is K = floor(A/2 - sqrt(A*A-N)/2).
All that remains is to find out the coordinates of a square that is N along the edge of some A x A matrix:
if 0*E <= N < 1*E, the coordinates are (0; N);
if 1*E <= N < 2*E, the coordinates are (N - E; E);
if 2*E <= N < 3*E, the coordinates are (E; 3*E - N); and
if 3*E <= N < 4*E, the coordinates are (4*E - N; 0).
Here, E = A - 1.
To conclude, here is a naive (layerNumber gives incorrect answers for large values of a due to float inaccuracy) Haskell implementation of this answer:
finalSquare :: Integer -> Integer -> Maybe (Integer, Integer)
finalSquare a n
| Just (x', y') <- edgeSquare a' n' = Just (x' + k, y' + k)
| otherwise = Nothing
where
k = layerNumber a n
a' = a - 2*k
n' = n - 4*(a-k)*k
edgeSquare :: Integer -> Integer -> Maybe (Integer, Integer)
edgeSquare a n
| n < 1*e = Just (0, n)
| n < 2*e = Just (n - e, e)
| n < 3*e = Just (e, 3*e - n)
| n < 4*e = Just (4*e - n, 0)
| otherwise = Nothing
where
e = a - 1
layerNumber :: Integer -> Integer -> Integer
layerNumber a n = floor $ aa/2 - sqrt(aa*aa-nn)/2
where
aa = fromInteger a
nn = fromInteger n
Here is the possible solution:
f a n | n < (a-1)*1 = (0, n)
| n < (a-1)*2 = (n-(a-1), a-1)
| n < (a-1)*3 = (a-1, 3*(a-1)-n)
| n < (a-1)*4 = (4*(a-1)-n, 0)
| otherwise = add (1,1) (f (a-2) (n - 4*(a-1))) where
add (x1, y1) (x2, y2) = (x1+x2, y1+y2)
This is a basic solution, it may be generalized further - I just don't know how much generalization you need. So you can get the idea.
Edit
Notes:
The solution is for 0-based index
Some check for existence is required (n >= a*a)
I'm going to propose a relatively simple workaround here which generates all the indices in O(A^2) time so that they can later be accessed in O(1) for any N. If A changes, however, we would have to execute the algorithm again, which would once more consume O(A^2) time.
I suggest you use a structure like this to store the indices to access your matrix:
Coordinate[] indices = new Coordinate[A*A]
Where Coordinate is just a pair of int.
You can then fill your indices array by using some loops:
(This implementation uses 1-based array access. Correct expressions containing i, sentinel and currentDirection accordingly if this is an issue.)
Coordinate[] directions = { {1, 0}, {0, 1}, {-1, 0}, {0, -1} };
Coordinate c = new Coordinate(1, 1);
int currentDirection = 1;
int i = 1;
int sentinel = A;
int sentinelIncrement = A - 1;
boolean sentinelToggle = false;
while(i <= A * A) {
indices[i] = c;
if (i >= sentinel) {
if (sentinelToggle) {
sentinelIncrement -= 1;
}
sentinel += sentinelIncrement;
sentinelToggle = !sentinelToggle;
currentDirection = currentDirection mod 4 + 1;
}
c += directions[currentDirection];
i++;
}
Alright, off to the explanation: I'm using a variable called sentinel to keep track of where I need to switch directions (directions are simply switched by cycling through the array directions).
The value of sentinel is incremented in such a way that it always has the index of a corner in our spiral. In your example the sentinel would take on the values 8, 15, 22, 28, 34, 39... and so on.
Note that the index of "sentinel" increases twice by 7 (8, 15 = 8 + 7, 22 = 15 + 7), then by 6 (28 = 22 + 6, 34 = 28 + 6), then by 5 and so on. In my while loop I used the boolean sentinelToggle for this. Each time we hit a corner of the spiral (this is exactly iff i == sentinel, which is where the if-condition comes in) we increment the sentinel by sentinelIncrement and change the direction we're heading. If sentinel has been incremented twice by the same value, the if-condition if (sentinelToggle) will be true, so sentinelIncrement is decreased by one. We have to decrease sentinelIncrement because our spiral gets smaller as we go on.
This goes on as long as i <= A*A, that is, as long as our array indices has still entries that are zero.
Note that this does not give you a closed formula for a spiral coordinate in respect to N (which would be O(1) ); instead it generates the indices for all N which takes up O(A^2) time and after that guarantees access in O(1) by simply calling indices[N].
O(n^2) hopefully shouldn't hurt too badly because I'm assuming that you'll also need to fill your matrix at some point which also takes O(n^2).
If efficiency is a problem, consider getting rid off sentinelToggle so it doesn't mess up branch prediction. Instead, decrement sentinelIncrement every time the while condition is met. To get the same effect for your sentinel value, simply start sentinelIncrement at (A - 1) * 2 and every time the if-condition is met, execute:
sentinel += sentinelIncrement / 2
The integer division will have the same effect as only decreasing sentinelIncrement every second time. I didn't do this whole thing in my version because I think it might be more easily understandable with just a boolean value.
Hope this helps!

suggest an algorithm for the following puzzle!

There are n petrol bunks arranged in circle. Each bunk is separated from the rest by a certain distance. You choose some mode of travel which needs 1litre of petrol to cover 1km distance. You can't infinitely draw any amount of petrol from each bunk as each bunk has some limited petrol only. But you know that the sum of litres of petrol in all the bunks is equal to the distance to be covered.
ie let P1, P2, ... Pn be n bunks arranged circularly. d1 is distance between p1 and p2, d2 is distance between p2 and p3. dn is distance between pn and p1.Now find out the bunk from where the travel can be started such that your mode of travel never runs out of fuel.
There is an O(n) algorithm.
Assume v[0] = p1 - d1, v[1] = p2 - d2, ... , v[n-1] = pn - dn. All we need to do is finding a starting point i, such that all the partial sum is no less than 0, i.e., v[i] >= 0, v[i] + v[(i+1)%n] >= 0, v[i] + v[(i+1)%n] + v[(i+2)%n] >= 0, ..., v[i]+...+v[(i+n-1)%n] >= 0.
We can find such a start point by calculating s[0] = v[0], s[1] = v[0]+v[1], s[2] = v[0]+v[1]+v[2], ..., s[n-1] = v[0] + ... + v[n-1], and pick up the minimum s[k]. Then the index (k+1)%n is the start point.
Proof: Assume the minimum element is s[k]. By the problem description, there must be the minimum s[k] <= 0.
Because the total sum v[0] + v[1] + ... + v[n-1] = 0, we have v[k+1] + v[k+2] + ... v[n-1] = -s[k] >= 0, and it is impossible that v[k+1] + ... v[j] < 0 (k < j < n). (Because if v[k+1] + ... v[j] < 0, then s[j] < s[k], which is contradictory with the assumption that s[k] is minimum.) So we have v[k+1] >= 0, v[k+1] + v[k+2] >= 0, ..., v[k+1] + v[k+2] + ... + v[n-1] >= 0.
Because s[k] is the minimum one, We also have v[k+1] + v[k+2] + ... + v[n-1] + v[0] = -s[k] + v[0] = -s[k] + s[0] >= 0, -s[k] + v[0] + v[1] = -s[k] + s[1] >= 0, ..., -s[k] + v[0] + v[1] + ... + v[k-1] = -s[k] + s[k-1] >= 0. So all the parital sum starting from (k+1) is no less than 0. QED.
Let's choose a junk algorithm that we know is wrong to see why it is wrong...
Notation...
Current Point: (gallons of gas at Current Point, gallons required to make next point)-> Remaining Gas (gallons)
In a little more mathematical form:
P[i]: (g(P[i]), d(P[i+1])) -> sum of (g(P[i]) - d(P[i+1])) from i=1 to current point-1
(And now for the bad algorithm...)
P1: (2,2) -> 0 (at P2)
P2: (5,3) -> 2 (at P3)
P3: (2,4) -> 0 (at P4)
P4: (2,5) -> -3 (ran out of gas 3 miles short of P5)
In order to make it to P5, we have to have three extra gallons of gas by the time we make it to P3, and in order to have 3 extra gallons at P3, we need to have 3 extra gallons at P1:
??? -> +3 (at P1)
P1: (2,2) -> 0+3 = 3 (at P2)
P2: (5,3) -> 2+3 = 5 (at P3)
P3: (2,4) -> 0+3 = 3 (at P4)
P4: (2,5) -> -3 +3 = 0 (made it to P5)
The trick, therefore, is to find the very worst sections -- where you are not given enough gas to traverse them. We know we can't start from P4, P3, P2, or P1. We have to start somewhere earlier and save up enough gas to make it through the bad section.
There will no doubt be multiple bad sections within the circle, making this somewhat complicated, but it's actually quite easy to figure out how to do this.
It's possible that the next few points following the very worst stretch in the circle could be traveled after the stretch, but only if they make no changes to your gas reserves. (e.g. the point after the worst stretch gives you 2 gallons of gas and makes you go 2 gallons of distance to the next point.)
In some cases, however, the worst section MUST be covered last. That's because before you start on that section, you need as much gas saved up as possible, and the next point after the worst stretch might give you the very last bit of gas that you need, which means you need to traverse it prior to taking on the worst stretch. Although there may exist multiple solutions, the simple fact of the matter is that traversing the worst section last is ALWAYS a solution. Here's some code:
class point_ {
int gasGiven_;
int distanceToNextPoint_;
public:
int gasGiven() {return gasGiven_;}
int distanceToNextPoint {return distanceToNextPoint_;}
}
class Circle_ {
public:
numberOfPoints;
point_ *P;
}
In main():
int indexWorstSection=0;
int numberPointsWorstSection=0;
int worstSum=0;
int currentSum=0;
int i=0;
int startingPoint =0;
// construct the circle, set *P to malloc of numberOfPoints point_'s, fill in all data
while (i<(Circle.numberOfPoints-1) || currentSum<0)
{
currentSum += Circle.P[i].gasGiven() - Circle.P[i].distanceToNextPoint();
if (currentSum < worstSum) { worstSum = currentSum; indexWorstSection=i-numberPointsWorstSection; startingPoint=i;}
if (currentSum>0) { currentSum=0; }
else { numberPointsWorstSection++; }
if (i==(Circle.numberOfPoints-1)) { i=0; }
else { i++; }
}
if (indexWorstSection<0) indexWorstSection=Circle.numberOfPoints+indexWorstSection;
The reason why you can't make it a for-loop is because the worst section might be, for example, from i=(Circle.numberOfPoints -2) to i=3. If the currentSum is under zero, it must continue back at the start of the array.
Haven't tried the code and haven't done any serious programming in almost a decade. Sorry if it has some bugs. You will no doubt have to clean this up a bit.
This does what several of the other answers do - finds the minimum of the "graph" created by the net-change-in-petrol deltas as you circle around. Depending on where we start, the exact values may be moved uniformly upwards or downwards compared to some other starting position, but the index of the minimal value is always a meaningful indication of where we can start and know we'll never run out of petrol. This implementation tries to minimise memory use and completes in O(n).
#include <iostream>
int dist[] = { 3, 10, 2, 4, 6, 9 };
int refill[] = { 3, 4, 6, 3, 7, 11 };
static const int n = sizeof dist / sizeof *dist;
int main()
{
int cum = 0, min = 0, min_index = 0;
for (int i = 0; i < n; ++i)
{
cum += refill[i] - dist[i];
std::cout << cum << ' ';
if (cum <= min)
{
min = cum;
min_index = i;
}
}
std::cout << "\nstart from index " << (min_index + 1) % n << " (0-based)\n";
}
See it running on ideone.com
Here's an approach that works in O(n) time and O(1) space. Start at any station, call it station 0, and advance until you run out of gas. If you don't run out of gas, done. Otherwise, if you run out between stations k and k+1, start over again at station k+1. Make a note if you pass 0 again, and if you run out after that it can't be done.
The reason this works is because if you start at station i and run out of gas between stations k and k+1, then you will also run out of gas before station k+1 if you start at any station between i and k.
Here's an algorithm, given an arrays P (petrol) and D (distance):
int position = 0;
int petrol = P[0];
int distance = D[0];
int start = 0;
while (start < n) {
while (petrol >= distance) {
petrol += P[++position % N] - distance;
distance = D[position % N];
if (position % N == start)
return start;
}
start = position;
petrol = P[start];
}
return -1;
Each leg of the trip has a net effect on fuel, adding from storage and using to make the trip. All you need to do is loop through once, keeping track of your fuel level when you arrive at each point, even if it is negative. Keep track of the lowest fuel level and which point it occurred on. If you start at that point, you will be able to make it around from there without running out of fuel. This assumes that you start with an empty tank and only get gas from the place you are starting, also that you can always take all the gas, you won't ever get full and have to leave gas behind.
Let's say you have 5 points, P1 to P5:
Point Fuel Distance to next point
P1 5 8
P2 3 4
P3 12 7
P4 1 4
P5 7 5
If you choose P1, then load up on 5 fuel, travelling to P2 leaves you with -3 fuel. Going on you get these numbers:
Point Fuel Balance (before refueling)
P1 0
P2 -3
P3 -4
P4 1
P5 -2
P1 0
So if you start at the lowest value, P3, you can make it back around (fuel 0 to start, 5 at P4, 2 at P5, 4 at P1, 1 at P2, 0 back at P3)
float [] storedFuel = { 1, 1, 1, 1, 1, 1 };
float [] distance = { 1, 1, 1, 1, 1, 1 };
int n = 6;
int FindMinimumPosition()
{
float fuel = 1;
int position = 0;
float minimumFuel = 1;
int minimumPosition = 0;
while (position < n)
{
fuel += storedFuel[position];
fuel -= distance[position];
position++; // could be n which is past array bounds
if (fuel < minimumFuel) {
minimumFuel = fuel;
minimumPosition = position % n;
}
}
return minimumPosition
}
Off the top of my head, here's an algorithm that should work:
let e1 = (the amount of petrol in P1) - d1 (i.e., the excess petrol in P1 over what is needed to travel to P2), and similarly for e2, ..., en. (These numbers can be positive or negative.)
Form the partial sums s1 = e1; s2 = e1 + e2; ..., sn = e1 + e2 + ... + en. We know from the conditions of the problem that sn = 0.
The problem now is to find a circular permutation of the bunks (or, more simply, of the e values) so that none of the s values are negative. One can simply repeatedly shift one, updating the s values, until a solution is found. (It's not immediately obvious that there is always a solution, but I think there is. If you shift n times without finding a solution, then you're guaranteed that there is none.)
This is an O(n^2) algorithm--not very good. A good heuristic (possibly an exact solution) may be to shift so that the largest-magnitude negative s value is shifted to position n.
For each gap, find the profit or loss earned by filling up at the bunk before the gap, and then crossing the gap. At an arbitrary point work out total amount of petrol remaining at each point of a complete circle, accepting that it may be negative at some point.
Now repeatedly circularly shift that solution. Remove the information for the last point, which will now be the first point. Set up an offset to take account of the fact that you are now starting one point further back, and will more (or less) petrol at each remaining point. Add in information for the new point, taking account of the offset. This solution is feasible if the minimum amount of petrol at any point, plus the offset, is greater than zero.
You can use some sort of log n data structure (sorted map, priority queue...) to keep track of the minimum so this takes the cost down to n log n.
Here is an O(n) solution
private int findStartingPoint(int[] petrol, int[] dist, int[] mileage){
int curPoint = 0;
boolean done = false;
while(curPoint < petrol.length && !done)
{
int prevPoint = curPoint;
int nextPoint = (curPoint+1) % petrol.length;
int nextSolutionPoint = curPoint + 1;
int totalPetrol = 0;
while(nextPoint != curPoint){
totalPetrol += petrol[prevPoint] - (dist[prevPoint]/mileage[prevPoint]);
if(totalPetrol < 0){
curPoint = nextSolutionPoint;
break;
}
prevPoint = nextPoint;
nextPoint = (nextPoint + 1) % petrol.length;
nextSolutionPoint++;
}
if(curPoint == nextPoint){
return curPoint;
}
}
return -1;
}
}

Fewest number of turns heuristic

Is there anyway to ensure the that the fewest number of turns heuristic is met by anything except a breadth first search? Perhaps some more explanation would help.
I have a random graph, much like this:
0 1 1 1 2
3 4 5 6 7
9 a 5 b c
9 d e f f
9 9 g h i
Starting in the top left corner, I need to know the fewest number of steps it would take to get to the bottom right corner. Each set of connected colors is assumed to be a single node, so for instance in this random graph, the three 1's on the top row are all considered a single node, and every adjacent (not diagonal) connected node is a possible next state. So from the start, possible next states are the 1's in the top row or 3 in the second row.
Currently I use a bidirectional search, but the explosiveness of the tree size ramps up pretty quickly. For the life of me, I haven't been able to adjust the problem so that I can safely assign weights to the nodes and have them ensure the fewest number of state changes to reach the goal without it turning into a breadth first search. Thinking of this as a city map, the heuristic would be the fewest number of turns to reach the goal.
It is very important that the fewest number of turns is the result of this search as that value is part of the heuristic for a more complex problem.
You said yourself each group of numbers represents one node, and each node is connected to adjascent nodes. Then this is a simple shortest-path problem, and you could use (for instance) Dijkstra's algorithm, with each edge having weight 1 (for 1 turn).
This sounds like Dijkstra's algorithm. The hardest part would lay in properly setting up the graph (keeping track of which node gets which children), but if you can devote some CPU cycles to that, you'd be fine afterwards.
Why don't you want a breadth-first search?
Here.. I was bored :-) This is in Ruby but may get you started. Mind you, it is not tested.
class Node
attr_accessor :parents, :children, :value
def initialize args={}
#parents = args[:parents] || []
#children = args[:children] || []
#value = args[:value]
end
def add_parents *args
args.flatten.each do |node|
#parents << node
node.add_children self unless node.children.include? self
end
end
def add_children *args
args.flatten.each do |node|
#children << node
node.add_parents self unless node.parents.include? self
end
end
end
class Graph
attr_accessor :graph, :root
def initialize args={}
#graph = args[:graph]
#root = Node.new
prepare_graph
#root = #graph[0][0]
end
private
def prepare_graph
# We will iterate through the graph, and only check the values above and to the
# left of the current cell.
#graph.each_with_index do |row, i|
row.each_with_index do |cell, j|
cell = Node.new :value => cell #in-place modification!
# Check above
unless i.zero?
above = #graph[i-1][j]
if above.value == cell.value
# Here it is safe to do this: the new node has no children, no parents.
cell = above
else
cell.add_parents above
above.add_children cell # Redundant given the code for both of those
# methods, but implementations may differ.
end
end
# Check to the left!
unless j.zero?
left = #graph[i][j-1]
if left.value == cell.value
# Well, potentially it's the same as the one above the current cell,
# so we can't just set one equal to the other: have to merge them.
left.add_parents cell.parents
left.add_children cell.children
cell = left
else
cell.add_parents left
left.add_children cell
end
end
end
end
end
end
#j = 0, 1, 2, 3, 4
graph = [
[3, 4, 4, 4, 2], # i = 0
[8, 3, 1, 0, 8], # i = 1
[9, 0, 1, 2, 4], # i = 2
[9, 8, 0, 3, 3], # i = 3
[9, 9, 7, 2, 5]] # i = 4
maze = Graph.new :graph => graph
# Now, going from maze.root on, we have a weighted graph, should it matter.
# If it doesn't matter, you can just count the number of steps.
# Dijkstra's algorithm is really simple to find in the wild.
This looks like same problem as this projeceuler http://projecteuler.net/index.php?section=problems&id=81
Comlexity of solution is O(n) n-> number of nodes
What you need is memoization.
At each step you can get from max 2 directions. So pick the solution that is cheaper.
It is something like (just add the code that takes 0 if on boarder)
for i in row:
for j in column:
matrix[i][j]=min([matrix[i-1][j],matrix[i][j-1]])+matrix[i][j]
And now you have lest expensive solution if you move just left or down
Solution is in matrix[MAX_i][MAX_j]
If you can go left and up too, than the BigO is much higher (I can figure out optimal solution)
In order for A* to always find the shortest path, your heuristic needs to always under-estimate the actual cost (the heuristic is "admissable"). Simple heuristics like using the Euclidean or Manhattan distance on a grid work well because they're fast to compute and are guaranteed to be less than or equal to the actual cost.
Unfortunately, in your case, unless you can make some simplifying assumptions about the size/shape of the nodes, I'm not sure there's much you can do. For example, consider going from A to B in this case:
B 1 2 3 A
C 4 5 6 D
C 7 8 9 C
C e f g C
C C C C C
The shortest path would be A -> D -> C -> B, but using spatial information would probably give 3 a lower heuristic cost than D.
Depending on your circumstances, you might be able to live with a solution that isn't actually the shortest path, as long as you can get the answer sooner. There's a nice blogpost here by Christer Ericson (progammer for God of War 3 on PS3) on the topic: http://realtimecollisiondetection.net/blog/?p=56
Here's my idea for an nonadmissable heuristic: from the point, move horizontally until you're even with the goal, then move vertically until you reach it, and count the number of state changes that you made. You can compute other test paths (e.g. vertically then horizontally) too, and pick the minimum value as your final heuristic. If your nodes are roughly equal size and regularly shaped (unlike my example), this might do pretty well. The more test paths you do, the more accurate you'd get, but the slower it would be.
Hope that's helpful, let me know if any of it doesn't make sense.
This untuned C implementation of breadth-first search can chew through a 100-by-100 grid in less than 1 msec. You can probably do better.
int shortest_path(int *grid, int w, int h) {
int mark[w * h]; // for each square in the grid:
// 0 if not visited
// 1 if not visited and slated to be visited "now"
// 2 if already visited
int todo1[4 * w * h]; // buffers for two queues, a "now" queue
int todo2[4 * w * h]; // and a "later" queue
int *readp; // read position in the "now" queue
int *writep[2] = {todo1 + 1, 0};
int x, y, same;
todo1[0] = 0;
memset(mark, 0, sizeof(mark));
for (int d = 0; ; d++) {
readp = (d & 1) ? todo2 : todo1; // start of "now" queue
writep[1] = writep[0]; // end of "now" queue
writep[0] = (d & 1) ? todo1 : todo2; // "later" queue (empty)
// Now consume the "now" queue, filling both the "now" queue
// and the "later" queue as we go. Points in the "now" queue
// have distance d from the starting square. Points in the
// "later" queue have distance d+1.
while (readp < writep[1]) {
int p = *readp++;
if (mark[p] < 2) {
mark[p] = 2;
x = p % w;
y = p / w;
if (x > 0 && !mark[p-1]) { // go left
mark[p-1] = same = (grid[p-1] == grid[p]);
*writep[same]++ = p-1;
}
if (x + 1 < w && !mark[p+1]) { // go right
mark[p+1] = same = (grid[p+1] == grid[p]);
if (y == h - 1 && x == w - 2)
return d + !same;
*writep[same]++ = p+1;
}
if (y > 0 && !mark[p-w]) { // go up
mark[p-w] = same = (grid[p-w] == grid[p]);
*writep[same]++ = p-w;
}
if (y + 1 < h && !mark[p+w]) { // go down
mark[p+w] = same = (grid[p+w] == grid[p]);
if (y == h - 2 && x == w - 1)
return d + !same;
*writep[same]++ = p+w;
}
}
}
}
}
This paper has a slightly faster version of Dijsktra's algorithm, which lowers the constant term. Still O(n) though, since you are really going to have to look at every node.
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.54.8746&rep=rep1&type=pdf
EDIT: THE PREVIOUS VERSION WAS WRONG AND WAS FIXED
Since a Djikstra is out. I'll recommend a simple DP, which has the benefit of running in the optimal time and not having you construct a graph.
D[a][b] is the minimal distance to x=a and y=b using only nodes where the x<=a and y<=b.
And since you can't move diagonally you only have to look at D[a-1][b] and D[a][b-1] when calculating D[a][b]
This gives you the following recurrence relationship:
D[a][b] = min(if grid[a][b] == grid[a-1][b] then D[a-1][b] else D[a-1][b] + 1, if grid[a][b] == grid[a][b-1] then D[a][b-1] else D[a][b-1] + 1)
However doing only the above fails on this case:
0 1 2 3 4
5 6 7 8 9
A b d e g
A f r t s
A z A A A
A A A f d
Therefore you need to cache the minimum of each group of node you found so far. And instead of looking at D[a][b] you look at the minimum of the group at grid[a][b].
Here's some Python code:
Note grid is the grid that you're given as input and it's assumed the grid is N by N
groupmin = {}
for x in xrange(0, N):
for y in xrange(0, N):
groupmin[grid[x][y]] = N+1#N+1 serves as 'infinity'
#init first row and column
groupmin[grid[0][0]] = 0
for x in xrange(1, N):
gm = groupmin[grid[x-1][0]]
temp = (gm) if grid[x][0] == grid[x-1][0] else (gm + 1)
groupmin[grid[x][0]] = min(groupmin[grid[x][0]], temp);
for y in xrange(1, N):
gm = groupmin[grid[0][y-1]]
temp = (gm) if grid[0][y] == grid[0][y-1] else (gm + 1)
groupmin[grid[0][y]] = min(groupmin[grid[0][y]], temp);
#do the rest of the blocks
for x in xrange(1, N):
for y in xrange(1, N):
gma = groupmin[grid[x-1][y]]
gmb = groupmin[grid[x][y-1]]
a = (gma) if grid[x][y] == grid[x-1][y] else (gma + 1)
b = (gmb) if grid[x][y] == grid[x][y-1] else (gma + 1)
temp = min(a, b)
groupmin[grid[x][y]] = min(groupmin[grid[x][y]], temp);
ans = groupmin[grid[N-1][N-1]]
This will run in O(N^2 * f(x)) where f(x) is the time the hash function takes which is normally O(1) time and this is one of the best functions you can hope for and it has a lot lower constant factor than Djikstra's.
You should easily be able to handle N's of up to a few thousand in a second.
Is there anyway to ensure the that the fewest number of turns heuristic is met by anything except a breadth first search?
A faster way, or a simpler way? :)
You can breadth-first search from both ends, alternating, until the two regions meet in the middle. This will be much faster if the graph has a lot of fanout, like a city map, but the worst case is the same. It really depends on the graph.
This is my implementation using a simple BFS. A Dijkstra would also work (substitute a stl::priority_queue that sorts by descending costs for the stl::queue) but would seriously be overkill.
The thing to notice here is that we are actually searching on a graph whose nodes do not exactly correspond to the cells in the given array. To get to that graph, I used a simple DFS-based floodfill (you could also use BFS, but DFS is slightly shorter for me). What that does is to find all connected and same character components and assign them to the same colour/node. Thus, after the floodfill we can find out what node each cell belongs to in the underlying graph by looking at the value of colour[row][col]. Then I just iterate over the cells and find out all the cells where adjacent cells do not have the same colour (i.e. are in different nodes). These therefore are the edges of our graph. I maintain a stl::set of edges as I iterate over the cells to eliminate duplicate edges. After that it is a simple matter of building an adjacency list from the list of edges and we are ready for a bfs.
Code (in C++):
#include <queue>
#include <vector>
#include <iostream>
#include <string>
#include <set>
#include <cstring>
using namespace std;
#define SIZE 1001
vector<string> board;
int colour[SIZE][SIZE];
int dr[]={0,1,0,-1};
int dc[]={1,0,-1,0};
int min(int x,int y){ return (x<y)?x:y;}
int max(int x,int y){ return (x>y)?x:y;}
void dfs(int r, int c, int col, vector<string> &b){
if (colour[r][c]<0){
colour[r][c]=col;
for(int i=0;i<4;i++){
int nr=r+dr[i],nc=c+dc[i];
if (nr>=0 && nr<b.size() && nc>=0 && nc<b[0].size() && b[nr][nc]==b[r][c])
dfs(nr,nc,col,b);
}
}
}
int flood_fill(vector<string> &b){
memset(colour,-1,sizeof(colour));
int current_node=0;
for(int i=0;i<b.size();i++){
for(int j=0;j<b[0].size();j++){
if (colour[i][j]<0){
dfs(i,j,current_node,b);
current_node++;
}
}
}
return current_node;
}
vector<vector<int> > build_graph(vector<string> &b){
int total_nodes=flood_fill(b);
set<pair<int,int> > edge_list;
for(int r=0;r<b.size();r++){
for(int c=0;c<b[0].size();c++){
for(int i=0;i<4;i++){
int nr=r+dr[i],nc=c+dc[i];
if (nr>=0 && nr<b.size() && nc>=0 && nc<b[0].size() && colour[nr][nc]!=colour[r][c]){
int u=colour[r][c], v=colour[nr][nc];
if (u!=v) edge_list.insert(make_pair(min(u,v),max(u,v)));
}
}
}
}
vector<vector<int> > graph(total_nodes);
for(set<pair<int,int> >::iterator edge=edge_list.begin();edge!=edge_list.end();edge++){
int u=edge->first,v=edge->second;
graph[u].push_back(v);
graph[v].push_back(u);
}
return graph;
}
int bfs(vector<vector<int> > &G, int start, int end){
vector<int> cost(G.size(),-1);
queue<int> Q;
Q.push(start);
cost[start]=0;
while (!Q.empty()){
int node=Q.front();Q.pop();
vector<int> &adj=G[node];
for(int i=0;i<adj.size();i++){
if (cost[adj[i]]==-1){
cost[adj[i]]=cost[node]+1;
Q.push(adj[i]);
}
}
}
return cost[end];
}
int main(){
string line;
int rows,cols;
cin>>rows>>cols;
for(int r=0;r<rows;r++){
line="";
char ch;
for(int c=0;c<cols;c++){
cin>>ch;
line+=ch;
}
board.push_back(line);
}
vector<vector<int> > actual_graph=build_graph(board);
cout<<bfs(actual_graph,colour[0][0],colour[rows-1][cols-1])<<"\n";
}
This is just a quick hack, lots of improvements can be made. But I think it is pretty close to optimal in terms of runtime complexity, and should run fast enough for boards of size of several thousand (don't forget to change the #define of SIZE). Also, I only tested it with the one case you have provided. So, as Knuth said, "Beware of bugs in the above code; I have only proved it correct, not tried it." :).

Resources