算法 穿越沙漠问题(递推法)

问题描述

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

问题分析

储油点地址的确定比较复杂,从出发点考虑问题,很难确保按要求以最少的耗油量穿越沙漠,即很难保证到达终点时,沙漠中的各临时油库和车的储油量都恰好为0。所以我们从终点向起点应用逆推法。
过程:

为了做到耗油最少,那么每次吉普车出发时都应满载放下一部分油再返回时,油恰好用完,并且把下一个油库建好后这个油库中的油恰好用完。所以每个点的油库中的油都应是吉普车装油量的整数倍(因为出发时满载),即500n(n为正整数),并且每个点的 存油量为下一个点的存油量及吉普车为建立下个油库在两点之间往返的油耗之和 (下一个油库建成,前一个油库中的油恰好用完)。

(1)由题可知,吉普车满载可以走500km。所以,第一段(即离终点最近的一段)长度为500km,并且,第一个加油点station_1(也是离终点最近的)的储油量为500L。
(2)那我们来看第二个加油点station_2。
它需要储存上一个加油点的储油量 + 车来往的耗油量。为了给station_1送500L油,车至少送两次油(因为中间路程要耗油嘛)。所以,车往返路程共3趟。
又考虑最少油耗,我们使这3趟路程耗油500L。那么station_2距station_1为500/3 = 167km,总共储油1000L。
(3)同样,我们看station_3。
为了给station_2送1000L油,至少送3次嘛,所以往返共5趟。
同样考虑耗油最少,那么station_3距station_2为 500/5 = 100km。

最后附上代码吧

/*
dis为储油点到终点的距离
*/

#include 

int main()
{
    int dis = 500, oil = 500;
    int k = 1;
    //因为不确定循环次数,又至少做一次,所以我们用do_while
    do
    {
        printf("储油点%d:距离出发点%5d,",k,1000-dis);
        printf("储油量%5dL\n",oil);
        k = k+1;
        dis = dis +500/(2*k-1);
        oil = 500*k;
    }while(dis<1000);

    // 再计算出发点的储油量
    oil = 500*(k-1)+(1000-dis)*(2*k-1);
    printf("储油点%d:距离出发点%5d,储油量%5dL\n",k,0,oil);

    return 0;
}

输出结果
算法 穿越沙漠问题(递推法)_第1张图片

你可能感兴趣的:(蓝桥杯,ACM)