了解加油站问题的算法


11

加油站问题中,我们给了个城市以及它们之间的道路。每条道路都有长度,每个城市都定义了燃料价格。一单位的道路需要一单位的燃料。我们的目标是以最便宜的方式从货源到目的地。我们的战车受到一些价值的限制。n{0,,n1}

我试图理解算法,所以我手动写下了计算解决方案的步骤。不幸的是,我被卡住了-在某些时候没有考虑的余地,我不知道为什么,也许我错过了一些东西。

示例:
道路:
0 ----------- 1 ------------ 2 -------------- 3
(不一定要这么简单,可以是任何图形,即0-> 2、0-> 3、1-> 3之间的道路等)

来源:0,目的地:3,坦克:10单位
燃油价格:0:10单位,1:10单位,2:20单位,3:12单位
长度:0-> 1:9单位,1-> 2:1单位,2-> 3:7单位
最佳解决方案:以0填充9个单位,以1填充8个单位,则总成本为170个单位(9 * 10 + 8 * 10)。

因此,我尝试按此处所示进行计算(第2.2段)

GV[u] is defined as:
GV[u] = { TankCapacity - length[w][u] | w in Cities and fuelPrice[w] < fuelPrice[v] and length[w][u] <= TankCapacity } U {0}

so in my case:
GV[0] = {0}
GV[1] = {0}
GV[2] = {0, 3, 9}
GV[3] = {0}

D(u,g) - minimum cost to get from u to t starting with g units of fuel in tank:
D(t,0) = 0, otherwise:
D(u,g) = min (foreach length[u][v] <= TankCapacity)
         { 
           D(v,0) + (length[u][v] - g) * fuelPrice[u]                             : if  fuelPrice[v] <= fuelPrice[u] and g <= length[u][v]
           D(v, TankCapacity - length[u][v]) + (TankCapacity - g) * fuelPrice[u]  : if  fuelPrice[v] > fuelPrice[u]
         }

so in my case:
D(0,0) = min { D(1,0) + 9*10 }  - D(0,0) should contain minimum cost from 0->3
D(1,0) = min { D(2,9) + 10*10 } - in OPT we should tank here only 8 units :(
D(2,9) = min { ??? - no edges which follows the condition from the reccurence 

Nevertheless D(0,0) = 90 + 100 + smth, so it's already too much.

To achieve the optimal solution algorithm should calculate D(2,7) because the optimal route is:   
(0,0) -> (1,0) -> (2, 7) -> (3, 0) [(v, g): v - city, g - fuel in tank]. 
If we look at G[2] there is no "7", so algorithm doesn't even assume to calculate D(2,7), 
so how can it return optimal solutions?

文档中的重复出现似乎无效,或者更有可能是我做错了。

有人可以帮我吗?

Answers:


7

问题在于min()p上的公式(4)中的第一个自变量的条件。7.目前

c(v) <= c(u) and g < d[u][v]

但这应该是

(c(v) <= c(u) or v = t) and g < d[u][v]

迫使到达t处没有气体。(就像下面我对Fill-Row(u,q)中的bug的解释一样,我们对t处的气体成本从不感兴趣。与之相同,解决此问题的另一种方法是覆盖c(t ),算法开头为0。)

修复此错误(在已发布的算法中),并添加我在下面描述的缺失边缘(您的错误:-P),足以使一切正常。


您缺少的一件事是,图G必须是完整的(第2节第1页,第4页)-如果它不完整,则必须添加任何缺失的边,并且权重可以通过选择最小路径长度来获得图。因此,例如在示例图中,(除其他外)应该存在一个权重为8(对应于通过2的路径)的,从1到3的边,因此实际上GV [3] = {0,2}。

我不确定这是否可以完全为您解决问题,但这应该有所帮助。

另外,我认为p的Fill-Row(u,q)算法中存在错误。6:此算法应专门处理q = 1的情况,但不是这样。我相信可以通过更改来解决

if c(v) <= c(u)

在3号线

if c(v) <= c(u) or q = 1

迫使任何一条最后的脚都空着到达目的地。(直觉上,我们应该始终不理会最终目的地的天然气价格,t。)解决此问题的另一种方法是,一开始将c(t)覆盖为0。


除了注意,当内部循环用完元素时,还需要注意用有意义的值填充表。而且,如果我正确地阅读了该算法,该算法似乎会完全忽略(请参见此CS SE问题),因此也需要在此做些事情。c v > c u q=1c(v)>c(u)
fuglede

2

使用@j_random_hacker解决方案,我们需要将图转换为完整图,并将条件从等式(4)更改为:

(c(v) <= c(u) or v = t) and g < d[u][v]     

完整的图形应如下所示:

在此处输入图片说明

和最终计算:

GV[0] = {0}, GV[1] = {0}, GV[2] = {0, 3, 9}, GV[3] = {0, 2}

D(0,0) = min { D(1,0) + 9 * 10 }
D(1,0) = min { D(2,9) + 10 * 10, D(3,0) + 8*10 }
D(3,0) = 0
... etc

so D(0,0) = 170

解决方案是通过0-> 1-> 3 [总费用170 $]。这就是我们所期望的:-)。如果需要一条路线,那么我们应该能够在一开始就将那些多余的边从解决方案转换为给定的边(这不是很困难)。

我只想知道在这种情况下如何避免死循环。例如,在0 <-> 1之间可能存在死循环,因为c(0)<= c(1)和c(1)<= c(0)。


供将来参考,请参阅此meta post :-)
Juho 2014年

1

想法是,无论您到哪里,都以最便宜的价格获得所需的燃料(贪婪算法范例)

举一些例子。在你的例子中

来源:0,目的地:3,坦克:10单位燃油价格:0:10单位,1:10单位,2:20单位,3:12单位长度:0-> 1:9单位,1-> 2:1单位,2-> 3:7单位

首先我必须旅行9个单位,所以我需要在> = 9个单位(容量> = 9)的情况下将我的水箱加满0。现在,我可以看到1,2,3时的燃油费率为> =燃油费率为0。因此,我想以最便宜的价格购买所需的燃油,因此我将尝试以9 + 1 + 7 = 17的单位填充仅城市0。但是,油箱的容量可能小于17,比如说10。所以,我要加油到10。然后在1时我剩下1个单位的燃料,而我又要遍历8个单位,所以在1时我要加满7个单位单位更多。我无法填满2点,因为利率会更高。我的总费用= 10 * 10 + 7 * 10 = 170。

贪婪算法遵循上述思想。 i座城市的燃料成本。两个城市和之间的距离。“满”是将油箱加满的燃料单位。“容量”是最大油箱容量。d ĴĴCidijij

i)满= 0

ii)对于到,令为之后的第一个城市,使得(如果不存在这样的,则)。 = more_distance_need_to_travel_till_city_ =。在城市购买 {满,容量}单位燃料。满= {满,容量}。设置。i=0n1liCi>Clll=n1dllk=i+1ldk,k+1mindlimindli=l


谢谢您的回答!不幸的是,我对自己的描述不够清楚。您认为,该图将简单到我的例子,但它可以是任何图形即可以有也道路0-> 2,1-> 3等
沃伊切赫·库利克

是的,正如您没有提到的,在我假设所有城市都以线性方式连接之前(图形是一条简单的路径)。
2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.