关于coolshell博客中的火车运煤问题的想法

刚看到陈皓博客上有一个关于火车运煤的面试题,趁着现在还没到上班点,就想了一下,具体题目如下:

 

你是山西的一个煤老板,你在矿区开采了有3000吨煤需要运送到市场上去卖,从你的矿区到市场有1000公里,你手里有一列烧煤的火车,这个火车最多只能装1000吨煤,且其能耗比较大——每一公里需要耗一吨煤。请问,作为一个懂编程的煤老板的你,你会怎么运送才能运最多的煤到集市?

 

这个问题初考虑的话,看似无解,不过稍加思考,不难得出还是有方法的,最容易想到的是运500吨到集市,也就是陈皓给出的第一个答案

 

 

  1. 装1000吨煤,走250公里,扔下500吨煤,回矿山。
  2. 装1000吨煤,走到250公里处,拿起250吨煤继续向前到500公里处,扔下500吨煤,回矿山。此时火车上还有250吨,再加上在250公里处还有250吨煤,所以,火车是可以回矿山的。
  3. 装上最后1000吨煤,走到500公里处,装上那里的500吨煤,然后一直走到目的。
然后我又想了一下,要想使得运最多的煤过去,那么应该是把矿场的煤全部运完,而且每次回矿场需要满载,这样的话使得回矿场的次数最少,从而使得耗费在路途上煤最少,那么也就是可以得出从矿场装煤的次数应该是
矿场装煤次数 =  总煤数/满载量
那么对应到这个题目就是3次

然后我们又根据火车走完全程所消耗的煤和自身的装载量是相同的,得出,火车肯定不能从矿场中途不停直接到集市,那样的话,是无法运煤到集市的,所以中途肯定需要装卸的过程,也就是需要分段运送,那么具体需要分几段,本题目中可能下意识的能想到分三段,但实际上这个分的段数是可以计算出来的。下面咱们来分析一下如何计算:

上面我们知道了从矿场装煤的次数应该是3次的情况最优,咱们假设矿场是A点,在中途需要装卸的第一点是B点,那么火车往返AB断的次数应该是3*2 -1 = 5次,为了得到最优的效果,在AB段往返所耗煤量应该和最大运载量相同,所以: 5*AB = 1000可以得出第一段应该200公里

然后此时B点煤还剩2000吨,由于火车一次装不完,所以我们可以知道,在剩下的路途中还需要停一次,我们定为C点,跟计算第一段类似 (2*2 -1) * BC = 1000,我们得出BC为333公里

走到C点只剩下1000吨了,所以这次火车可以直接到集市了,我们把集市定位D点,由此得出

AB + BC + CD = 1000可以得到CD段位467,所以最后运到集市的煤为533吨

那么我们也可以把上面的思路转换成代码

private void cal1(int total,int distance) {
                //总装载量,当然我们也可以写成变量
		int cargoCapacity = 1000;
                //计算需要装载的次数
		int count = total/cargoCapacity;
                //如果计算结果小于等于1,说明只需再运一次就到终点了,所以调用结束
		if (count <= 1) {
			finalCount = distance;
			return;
		}
                //计算子路程的大小
		int subDistance = 1000/(count * 2 - 1);
                //递归调用
		if (distance - subDistance >= 0){
			cal1((total - cargoCapacity),distance - subDistance);
		}
			
	}
 
 大概就想了这么多,要工作了,没时间多想了,可能这个思路还有点问题,希望大家批评指正,也一起讨论

 

你可能感兴趣的:(编程,C++,c,面试,C#)