问题
I was in a trading firm interview, I was asked this question,
you are travelling accross the state in a buses, the buses can stop at any C possible cities and you need to find a way to go from city a to city b. There are total B buses, each of which travels between two cities. All buses travel on a daily bases, for example each bus x leaves some city c1 on day d1 and arrives at another city b1 on another day d2 (d2>d1). Assume that if you arrive at a city on day d, you can catch any bus leaving the city on day d or after.
you are given a1, b1,d1, and d2 for B buses. describe an algorithm that determines whether there exist a route from city a to city b in no more than D days, and analyze the run time.
I was initially try to model the problem in to shortest path algorithm but I could not figure out at that moment, I screwed the interview.
回答1:
I thought if you were given a day to start from (which doesn't seem to be the case), it should be easy to apply Dijkstra's algorithm.
It's trivial to create a graph for the problem. Each node is a city, each bus is a directed edge from one node to another. The weight of an edge isn't really defined in general (we can't just take the trip time) and will be determined when we process it.
So, reduce the problem to multiple sub-problems where you know the start day, as follows:
From a there are k busses to other cities. So bus bi goes from a to bi from day starti to day endi. For each of these busses, create a sub-problem starting from bi on day endi (and remember starti).
To do Dijkstra given a starting day and city:
When exploring the graph, we need to keep track of the current day.
When generating neighbors at a city c1 from day d1, for each city c2 where there is a bus from c1 to c2, we generate the earliest bus from c1 to c2 (where depart at c1 >= the current day) (if busses can take different amounts of days to get from c1 to c2, consider the earliest arrive at c2). The value of c2 would simply be the number of days from the original starting day (starti from above) to the day the bus arrives at c2.
Optimization:
You don't need to do a complete run of Dijkstra on each subproblem, if you arrived at a city on a certain day, any next subproblem that arrives at that city on the same day would have the same path from there onward. Doing them all at the same time shouldn't be too difficult and should result in better performance than doing them one at a time.
One may be able to come up with a heuristic function to be able to apply A*.
Feel free to point out if I missed something.
回答2:
Fun Problem. Here's my attempt. Let me know if I'm overlooking something important or if something in my solution is unclear.
Tip 1: If the problem looks hard, reduce it to something simpler. Solve the simpler problem, and see if you can generalize your solution to the harder case.
Let's apply the trick here. We know that buses go between two cities. In order to simplify assume that if a bus goes from one city to another we can always go between these two nodes. So build an undirected graph where the vertices are the cities. Now there is an edge between vertices i and j, if there is ever a bus that would go from i to j (same as going from j to i). Now in this case the problem is simply if we are interested in starting at a and ending at b of length < n, does the shortest path have length less than n. Great!
Now lets move back to the harder problem. We build two graphs G_1 and G_2, G_1 represents the places we can get given the day is odd numbered (like day 1), and G_2 represents the places we can get given the day is even numbered (like day 2). Now both of these graphs are directed unlike previously. Now we combine these two graphs to form the graph G. The vertices of G are simply G_1 union G_2. Now for every directed edge in G_1, denote the start vertex s and the end vertex t. Connect vertex s in G_1 (as a subgraph of G) to vertex t in G_2 (as a subgraph of G). For every directed edge in G_2, denote the start vertex s and end vertex t. Connect vertex s in G_2 (as a subgraph of G) to vertex t in G_1 (as a subgraph of G). All directed edges in G have weight 1. Now the problem is simply does there exist a shortest path in G of length < n.
The idea is of overlaying the two graphs G_1 ontop of G_2 so that we take into account that the routes change on even and odd days.
回答3:
Here's an example in Haskell with real slow buses, constructing routes from destination back to origin:
import Data.List (elemIndex)
import Data.Maybe (fromJust)
cities = ["New York", "Philadelphia", "Washington", "Buffalo"]
buses = [([0,1],2), ([0,2],1), ([1,2],1), ([2,3],4)] --buses (cities a1 b1 as indexes, num days of travel)
solve origin destination maxDays = do
lastBus <- filter ((== fromJust (elemIndex destination cities)) . last . fst) buses
solve' [lastBus] where
solve' result
| sum (map snd result) > maxDays = []
| cities !! (head . fst . head $ result) == origin =
[(map (map (cities !!) . fst) result, show (sum . map snd $ result) ++ " Days Travel")]
| otherwise =
let potentialBuses = filter ((== (head . fst . head $ result)) . last . fst) buses
in if null potentialBuses
then []
else do
bus <- potentialBuses
solve' (bus:result)
OUTPUT:
*Main> solve "New York" "Buffalo" 6
[([["New York","Washington"],["Washington","Buffalo"]],"5 Days Travel")]
*Main> solve "New York" "Buffalo" 3
[] --trip longer than D
*Main> solve "New York" "Washington" 3
[([["New York","Washington"]],"1 Days Travel"),
([["New York","Philadelphia"],["Philadelphia","Washington"]],"3 Days Travel")]
回答4:
There is another method that you will find mentioned now and then. It's based on a matrix that defines possible transitions between cities. Assuming the matrix is M, then M[i,j] is 1 if there is a road from city j to city i, otherwise 0. By starting with a unit vector for the start city and multiplying that vector with the transition matrix, you will get a vector with a value greater zero in all cities that can be reached within a single step. You repeat this step for the requested number of days.
When modelling your case, a problem is that you have a weighted graph, i.e. not every transition takes the same time. However, that cost is an integral number, so you could introduce artificial stops (i.e. vertices) in the routes that take more than a day to model this. You would then end up with an unweighted graph. Further, you can assume from the question that the weight is low, so it probably doesn't cause much overhead.
Since matrix multiplication is associative, you can multiply the matrix with itself several times before feeding it the initial vector. Since the actual values are not of interest, only whether they are 0 or 1, you might be able to further reduce this and efficiently bit-pack the matrix. Further, you can compute MxMxMxM as (MxM)x(MxM) to reduce the overhead. Then, there are also some optimizations to matrix multiplication (Strassen Algorithm, IIRC) that could be harvested.
Note: I know this description is a bit sketchy, just drop me a note and I'll try to clarify it.
来源:https://stackoverflow.com/questions/15938954/is-there-is-a-route-from-city-a-to-city-b-in-no-more-than-x-days