穿越沙漠问题---递推法

一、问题描述

  一辆吉普车来到1000km宽的沙漠边沿。吉普车的耗油量为1L/km,总装油量为500L。显然,吉普车必须用自身油箱中的油在沙漠中设几个临时 加油点,否则是通不过沙漠的。假设在沙漠边沿有充足的汽油可供使用,那么吉普车应在哪些地方、建多大的临的加油点,才能以最少的油耗穿过这块沙漠?

二、问题解析

  1. 以最少的油耗穿过
      油耗要求最少,则意味着该车从起点到达终点时各临时加油点的油量全部使用完毕,没有浪费;在每个加油点加油都需要加满500L,因此可知每个加油点的存储油量都会是500的整数倍。
  2. 倒推法进行推导
      根据题意,起点油量充足,到达终点时汽油应该刚好使用完,则距终点第一个加油站容量500L,距终点距离500km;则距终第一个加油站油量运送由距终第二个加油站负责,500L汽油需要运送2次(装油量为500L),则经过两点的距离3次,则距终第二个加油站油量= 路上消耗油量+距终第一个加油站油量;往后依次类推

图示如下:

第一次:V1 = 500L 距B为500KM

第二次:V2 =3 * X+V1= 2 * 500 ==> X = 500/3 KM,距B为 (1+1/3) * 500 KM

第三次:V3 =5 * X+V2 = 3 * 500 ==> X = 100 KM,距B为 (2+1/3)*500 KM

   图与上类似,省略咯!

第i次:Vi = (2i-1)Xi + Vi-1 = i * 500 ==> x = (v2 - v1) / (2*i - 1);

三、代码示例

    void acrossDesert() {
        int i = 0;//加油点数量(从终点开始算)
        double  v1 = 0, v2 = 0;//加油点油量
        double d = 0;//距终点距离
        double x = 0;//各加油点之间距离

        double xx = 0;//起点矫正量
        double totalOil = 0;//总油耗

        while (d < 1000) {
            //Vi = (2i-1)Xi + Vi-1 = i * 500(推导公式)

            i++;

            v1 = (i - 1)* 500;//上一个加油点存储油量
            v2 = i * 500;//本加油点存储油量
            x = (v2 - v1) / (2*i - 1);//加油点距离公式
            d += x;//累加至距终点距离
            totalOil += (2 * i - 1)*x;

            if (d > 1000) {//起点固定  进行矫正
                xx = d - 1000;
                d = 1000;
            }
            cout << "距起点"<< (1000-d)<<"公里处为第" <<i << "个临时加油点,油量:" << v2<<endl;
        }

        totalOil -= xx*(2*i-1);//矫正为xx公里,根据推到的公式本应行经(2*i-1)次
        cout << "总耗油量:" << totalOil;

    }

结果: