我是在一个贸易公司采访时,有人问我这个问题,
你旅行翻过在公交车的状态下,公交车可以在任何C可能停止的城市,你需要找到一种方式,从城市去B城。 有总B总线,其每一个的两个城市之间行进。 所有公交车行驶在每日基地,例如每个总线X叶日D1一些城市C1,并在另一天D2(D2> D1)又一城B1到达。 假设,如果你在一天d到达一个城市,你可以捕获任何公共汽车上留下d天或之后的城市。
您将得到A1,B1,D1和D2对于B总线。 描述确定是否存在在不超过d天以上存在从城市的路线来B市算法,并分析了运行时间。
我最初尝试的问题,以最短路径算法模型,但我不能在那一刻弄清楚,我搞砸了采访。
我想如果给你一天从开始(这似乎并不如此),它应该很容易申请Dijkstra算法 。
这是微不足道的创造该问题的图。 每个节点是一个城市,每个总线是从一个节点到另一个的有向边。 边缘的重量是不是真的在一般的定义(我们不能只把行程时间),当我们处理它会被确定。
因此, 减少问题的地方,你知道开始日 ,如下多个子问题 :
从一个有k个公共汽车到其他城市。 所以,总线B, 我从前进到B I从第一天开始我一天结束我 。 对于这些总线,创建一个子问题,从B I开始一天结束时,我 (记得开始我 )。
要做到Dijkstra算法给出一个出发日期和城市:
当游览图,我们需要跟踪当前的一天。
当在城市C1从日D1,为每个城市C2那里有一个总线从C1到C2生成的邻居,我们从C1到C2产生最早的总线(其中在C1出发> =当前日期)(如果总线可以采取不同数量的天,从C1到C2,考虑最早在C2到达)。 C2的值将仅仅是从原来的出发日的天数(从上面开始我 )到总线到达C2的一天。
优化:
你不需要做Dijkstra算法的完整运行在每个子问题,如果你在某一天来到一个城市,即到达该城市在同一天的任何下一子问题必须从那里起相同的路径。 否则他们都在同一时间应该不会太困难,并且会导致更好的表现比他们做一次一个。
一个可能能够拿出一个启发式功能,能够应用A * 。
随意指出,如果我错过了一些东西。
有趣的问题。 这里是我的尝试。 让我知道如果我俯瞰一些重要的或某些东西在我的解决方案还不清楚。
提示1:如果问题看起来很难,将其降低到更简单的东西。 解决简单的问题,看看你是否能概括你解决困难的情况下。
让我们在这里适用的伎俩。 我们知道,公交车两个城市之间去。 为了简化假设,如果总线从一个城市转到另一个我们总能在这两个节点之间去。 因此,建立一个无向图,其中顶点是城市。 现在有顶点i和j之间的边缘,如果有过一个总线将从我去到j(同从j去我)。 现在,在这种情况下,这个问题很简单,如果我们有兴趣开始于一个和长度说明B结束<N,确实最短路径有长度小于n。 大!
现在,让我们回迁困难的问题。 我们建立两个图G_1和G_2,G_1代表我们可以得到给定的一天奇数编号(如1天)的地方,和G_2代表我们可以得到给定的一天偶数(如2天)的地方。 现在,这两个图表都不像以前执导。 现在我们结合这两个图形成图G G的顶点只是G_1工会G_2。 现在对于在每G_1向边,表示起始顶点S和结束顶点吨。 顶点S IN G_1(作为G的子图)连接到顶点吨G_2(作为G的子图)。 对于每G_2向边,表示起始顶点S和结束顶点吨。 顶点S IN G_2(作为G的子图)连接到顶点吨G_1(作为G的子图)。 在G中所有有向边具有重量1现在的问题是简单地做在G中存在的最短路径长度的<N。
我们的想法是覆盖在两个图G_1 G_2 ontop的,使我们考虑到的路由改变奇数和偶数天。
下面是在Haskell与真正的慢巴士,从目的地建设路线回原籍一个例子:
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")]
还有,你会发现现在再提到的另一种方法。 它是基于一个定义城市之间可能的转换矩阵。 假设矩阵是M,则M [I,J]为1,如果有从一个城市J可市我的道路,否则为0。通过与用于开始的城市的单位矢量起始和向量乘以与过渡矩阵,则将获得更大的零,可以单步内到达所有城市的值的矢量。 您重复此步骤天的请求数量。
当你的建模情况下,问题是,你有一个加权图,即不是每个过渡需要同时进行。 然而,成本是一个整数,所以你可以介绍在采取一天以上,以模拟这种路线人工停止(即顶点)。 这样,你会用加权图表结束。 此外,你可以质疑,认为重量低假设,所以它可能不会造成多大的开销。
由于矩阵乘法是关联的,你可以用自己多次喂养它的初始向量前乘矩阵。 由于实际值是不感兴趣,他们只是否为0或1,你也许能够进一步降低这一点,并有效位打包矩阵。 此外,你可以计算MxMxMxM为(MXM)×(MXM),以减少开销。 然后,也有一些优化,以矩阵乘法(Strassen的算法,IIRC)可能会有所收获。
注:我知道这个描述是有点粗略,只是给我发一张纸条,我会尽力澄清。