类Runtime和火车运煤问题
1 类Runtime
每个 Java 应用程序都有一个 Runtime
类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime
方法获取当前运行时。
应用程序不能创建自己的 Runtime 类实例。
2 火车运煤问题
问题来源:http://coolshell.cn/articles/4429.html/comment-page-5#comments
你是山西的一个煤老板,你在矿区开采了有3000吨煤需要运送到市场上去卖,从你的矿区到市场有1000公里,你手里有一列烧煤的火车,这个火车最多只能装1000吨煤,且其能耗比较大——每一公里需要耗一吨煤。请问,作为一个懂编程的煤老板的你,你会怎么运送才能运最多的煤到集市?
假设运到集市的煤的重量为left,我们可以假设火车在某处捡了left吨煤,则该问题可转化为问题二:
条件:最大容量为capacity的火车,把煤运到pick_location处后,扔下left吨煤然后返回原地,刚好消耗掉min_coal吨煤。
问题一:根据left求min_coal。
问题二:根据min_coal求left。
问题一
我们先求取问题一
运left吨煤到集市,至少需要矿区煤的重量为min_coal = distance + min_coal(capacity, left, left)。
其中min_coal(capacity, pick_location, left)为问题一的解,表示最大容量为capacity的火车,把煤运到pick_location处后,扔下left吨煤然后返回原地,刚好消耗掉所有的煤的情况下,矿区的煤的最小重量min_coal。
1 left < 0时,min_coal = 0;
2 pick_location * 2 + left < capacity时,min_coal = pick_location * 2 + left
3 其他,min_coal = pick_location * 2 + min_coal(capacity, new_left/2, new_left)
其中new_left = pick_location * 2 + left - capacity,火车去时,在new_left/2处拿起new_left/2吨煤,然后在new_left处放下new_left吨煤,再在回来时,在new_left/2处拿起new_left/2吨煤。
根据该方案可求得:
left = 529时,矿区最少煤量为2989
即本题答案至少为529
问题二
对于问题二,假设矿区为A、集市为D,两者之间有两个点B、C可以存煤。
1 A区有煤3000吨,火车最大容量为1000,即需要从A出发三次,由于只有一列火车,需要回来二次。
2 B有煤2000吨,即需要从B出发二次,从C回到B一次。
3 C有煤1000吨,火车装满后直接奔赴D,只有一次。
即5AB=1000,3BC=1000,AB+BC+CD = 1000,即CD=7/15*1000,left = 8/15 * 1000=533
至于这里为何在B处和C处出发时为1000,是因为出发时装煤量为0~1000,而该线性问题,解为临界值,不可能为0,只能为1000。
求得结果后代入验证,发现533满足题意,即该题的解至少为533。
也即,如果min_coal的值发生变化,left的值也会变化
min_coal = 2000, left = 1000 * (1/3) = 1000 * 1/3
min_coal = 3000, left = 1000 * (1/3 + 1/5 = 1000 * 8/15
min_coal = 4000, left = 1000 * (1/3 + 1/5 + 1/7) = 1000 * 71/105
min_coal = 5000, left = 1000 * (1/3 + 1/5 + 1/7 + 1/9) = 1000 * 248 / 315
但当min_coal = 7000时,按此公式计算的left > 1,也即最后可以运1000以上的煤到集市,这时就过了临界值,需要用另一个公式了。
该思路对另一种情况也需要重新考虑,矿区煤量不为整千,如min_coal = 3400时。
扩展问题:
1 耗煤量与载媒量有关时。
2 矿区总媒量变化的情况。
问题一代码如下:
# 最大容量为capacity的火车,把煤运到distance处后,还剩下left吨煤。
# 返回值:煤的最小重量min_coal。
def train(distance, capacity, left): if(left < 0): return 0; if(left < distance/3): return distance + left * 3 return distance + min_coal(capacity, left, left) # 最大容量为capacity的火车,把煤运到pick_location处后,扔下left吨煤然后返回原地,刚好消耗掉所有的煤 # 返回值:煤的最小吨数min_coal。 def min_coal(capacity, pick_location, left): print "pick_location", pick_location print "left: ", left if(left < 0): return 0 if(pick_location * 2 + left < capacity): return pick_location * 2 + left new_left = pick_location * 2 + left - capacity # 需要在路上捡new_left吨煤,最少得在new_left处捡 new_pick_location = new_left / 2 return pick_location * 2 + min_coal(capacity, new_pick_location, new_left)