动态最短路径
Dyanmic Shortest Path
你的朋友正计划去加拿大北部深处的一个小镇探险
下一个寒假。他们研究了所有的旅行选择,并制定了一个有方向的
其节点代表中间目的地和边缘代表之间的重新加载的图
他们。
在此过程中,他们还了解到极端天气导致这部分地区的道路
世界在冬天变得相当缓慢,可能会导致大量旅行延误。他们已经
找到了一个出色的旅游网站,可以准确预测他们能够以多快的速度到达
沿着道路行驶;然而,旅行的速度取决于一年中的时间。更多的
准确地说,网站会回答以下形式的查询:给定一条边 e = (u, v)
连接两个站点 u 和 v,并给定从位置 u 开始的建议开始时间 t,则
站点将 return 值 fe(t),即 v 的预测到达时间。该网站保证
1个
fe(t) > t 对于每个边 e 和每个时间 t(你不能及时倒退),并且
fe(t) 是 t 的单调递增函数(也就是说,您不会通过开始
之后)。除此之外,函数fe 可以是任意的。例如,在
旅行时间不随季节变化,我们将有 fe(t) = t + e, where
e 是
从边缘 e 的起点行进到终点所需的时间。
您的朋友想要使用该网站来确定最快的旅行方式
从起点到预定目的地的有向图。 (你应该假设
它们从时间 0 开始并且网站所做的所有预测都是完全正确的
正确。)给出多项式时间算法来执行此操作,我们将单个查询视为
网站(基于特定的边缘 e 和时间 t)采取单个计算步骤。
def updatepath(node):
randomvalue = random.randint(0,3)
print(node,"to other node:",randomvalue)
for i in range(0,n):
distance[node][i] = distance[node][i] + randomvalue
def minDistance(dist,flag_array,n):
min_value = math.inf
for i in range(0,n):
if dist[i] < min_value and flag_array[i] == False:
min_value = dist[i]
min_index = i
return min_index
def shortest_path(graph, src,n):
dist = [math.inf] * n
flag_array = [False] * n
dist[src] = 0
for cout in range(n):
#find the node index that have min cost
u = minDistance(dist,flag_array,n)
flag_array[u] = True
updatepath(u)
for i in range(n):
if graph[u][i] > 0 and flag_array[i]==False and dist[i] > dist[u] + graph[u][i]:
dist[i] = dist[u] + graph[u][i]
path[i] = u
return dist
我应用了 Dijkstra 算法,但它不正确?我会在我的算法中更改什么以使其适用于动态变化的边缘。
好吧,关键点是函数是单调递增的。有一种算法利用了这个 属性,它被称为 A*。
累计成本:你的教授希望你使用两个距离,一个是累计成本(这很简单,将之前的成本添加到 cost/time 需要移动到下一个节点)。
启发式成本:这是一些预测成本。
Disjkstra 方法不起作用,因为您使用的是 启发式 cost/predicted 和 累积成本 。
单调递增意味着 h(A) <= h(A) + f(A..B)。它只是说如果你从节点 A 到节点 B 则成本不应小于前一个节点(在本例中为 A),这是 heuristic + accumulated. 如果这个 属性 成立,那么 A* 选择的第一条路径永远是通往目标的路径,它永远不需要回溯。
注意:该算法的威力完全取决于您如何预测价值。
如果你低估了这个值,就会用累加值修正,但如果你高估了这个值,它就会选择错误的路径。
算法:
Create a Min Priority queue.
insert initial city in q.
while(!pq.isEmpty() && !Goalfound)
Node min = pq.delMin() //this should return you a cities to which your
distance(heuristic+accumulated is minial).
put all succesors of min in pq // all cities which you can reach, you
can better make a list of visited
cities s that queue will be
efficient by not placing same
element twice.
Keep doing this and at the end you will either reach goal or your queue will be empty
额外
这里我使用 A* 实现了一个 8 拼图解决方案,它可以让您了解成本是如何定义的以及它是如何工作的。
`
private void solve(MinPQ<Node> pq, HashSet<Node> closedList) {
while(!(pq.min().getBoad().isGoal(pq.min().getBoad()))){
Node e = pq.delMin();
closedList.add(e);
for(Board boards: e.getBoad().neighbors()){
Node nextNode = new Node(boards,e,e.getMoves()+1);
if(!equalToPreviousNode(nextNode,e.getPreviousNode()))
pq.insert(nextNode);
}
}
Node collection = pq.delMin();
while(!(collection.getPreviousNode() == null)){
this.getB().add(collection.getBoad());
collection =collection.getPreviousNode();
}
this.getB().add(collection.getBoad());
System.out.println(pq.size());
}
link 到 full 代码在这里。
你的朋友正计划去加拿大北部深处的一个小镇探险
下一个寒假。他们研究了所有的旅行选择,并制定了一个有方向的
其节点代表中间目的地和边缘代表之间的重新加载的图
他们。
在此过程中,他们还了解到极端天气导致这部分地区的道路
世界在冬天变得相当缓慢,可能会导致大量旅行延误。他们已经
找到了一个出色的旅游网站,可以准确预测他们能够以多快的速度到达
沿着道路行驶;然而,旅行的速度取决于一年中的时间。更多的
准确地说,网站会回答以下形式的查询:给定一条边 e = (u, v)
连接两个站点 u 和 v,并给定从位置 u 开始的建议开始时间 t,则
站点将 return 值 fe(t),即 v 的预测到达时间。该网站保证
1个
fe(t) > t 对于每个边 e 和每个时间 t(你不能及时倒退),并且
fe(t) 是 t 的单调递增函数(也就是说,您不会通过开始
之后)。除此之外,函数fe 可以是任意的。例如,在
旅行时间不随季节变化,我们将有 fe(t) = t + e, where
e 是
从边缘 e 的起点行进到终点所需的时间。
您的朋友想要使用该网站来确定最快的旅行方式
从起点到预定目的地的有向图。 (你应该假设
它们从时间 0 开始并且网站所做的所有预测都是完全正确的
正确。)给出多项式时间算法来执行此操作,我们将单个查询视为
网站(基于特定的边缘 e 和时间 t)采取单个计算步骤。
def updatepath(node):
randomvalue = random.randint(0,3)
print(node,"to other node:",randomvalue)
for i in range(0,n):
distance[node][i] = distance[node][i] + randomvalue
def minDistance(dist,flag_array,n):
min_value = math.inf
for i in range(0,n):
if dist[i] < min_value and flag_array[i] == False:
min_value = dist[i]
min_index = i
return min_index
def shortest_path(graph, src,n):
dist = [math.inf] * n
flag_array = [False] * n
dist[src] = 0
for cout in range(n):
#find the node index that have min cost
u = minDistance(dist,flag_array,n)
flag_array[u] = True
updatepath(u)
for i in range(n):
if graph[u][i] > 0 and flag_array[i]==False and dist[i] > dist[u] + graph[u][i]:
dist[i] = dist[u] + graph[u][i]
path[i] = u
return dist
我应用了 Dijkstra 算法,但它不正确?我会在我的算法中更改什么以使其适用于动态变化的边缘。
好吧,关键点是函数是单调递增的。有一种算法利用了这个 属性,它被称为 A*。
累计成本:你的教授希望你使用两个距离,一个是累计成本(这很简单,将之前的成本添加到 cost/time 需要移动到下一个节点)。
启发式成本:这是一些预测成本。
Disjkstra 方法不起作用,因为您使用的是 启发式 cost/predicted 和 累积成本 。
单调递增意味着 h(A) <= h(A) + f(A..B)。它只是说如果你从节点 A 到节点 B 则成本不应小于前一个节点(在本例中为 A),这是 heuristic + accumulated. 如果这个 属性 成立,那么 A* 选择的第一条路径永远是通往目标的路径,它永远不需要回溯。
注意:该算法的威力完全取决于您如何预测价值。
如果你低估了这个值,就会用累加值修正,但如果你高估了这个值,它就会选择错误的路径。
算法:
Create a Min Priority queue.
insert initial city in q.
while(!pq.isEmpty() && !Goalfound)
Node min = pq.delMin() //this should return you a cities to which your
distance(heuristic+accumulated is minial).
put all succesors of min in pq // all cities which you can reach, you
can better make a list of visited
cities s that queue will be
efficient by not placing same
element twice.
Keep doing this and at the end you will either reach goal or your queue will be empty
额外
这里我使用 A* 实现了一个 8 拼图解决方案,它可以让您了解成本是如何定义的以及它是如何工作的。
`
private void solve(MinPQ<Node> pq, HashSet<Node> closedList) {
while(!(pq.min().getBoad().isGoal(pq.min().getBoad()))){
Node e = pq.delMin();
closedList.add(e);
for(Board boards: e.getBoad().neighbors()){
Node nextNode = new Node(boards,e,e.getMoves()+1);
if(!equalToPreviousNode(nextNode,e.getPreviousNode()))
pq.insert(nextNode);
}
}
Node collection = pq.delMin();
while(!(collection.getPreviousNode() == null)){
this.getB().add(collection.getBoad());
collection =collection.getPreviousNode();
}
this.getB().add(collection.getBoad());
System.out.println(pq.size());
}
link 到 full 代码在这里。