天天看點

實用算法(基礎算法-遞推法-01)

推關系式:

    F n=g(F n-1)

    這就在數的序列中,建立起後項和前項之間的關系,然後從初始條件(或最終結果)入手,一步步地按遞推關系遞推,直至求出最終結果(或初始值)。很多程式就是按這樣的方法逐漸求解的。如果對一個試題,我們要是能找到後一項與前一項的關系并清楚其起始條件(最終結果),問題就好解決,讓計算機一步步算就是了,讓高速的計算機做這種重複運算,可真正起到“物盡其用”的效果。

    遞推分倒推法和順推法兩種形式。一般分析思路:

    if求解條件F1

        then begin{倒推}

            由題意(或遞推關系)确定最終結果Fa;

            求出倒推關系式F i-1=g'(F i);

            i=n;{從最終結果Fn出發進行倒推}

            while 目前結果F i非初始值F 1 do由F i-1=g(F 1)倒推前項;

            輸出倒推結果F 1和倒推過程;

            end {then}

        else begin{順推}

            由題意(或順推關系)确定初始值F1(邊界條件);

            求出順推關系式F1=g(Fi-1);

            i=1;{由邊界條件F1出發進行順推}

            while 目前結果Fi非最終結果Fn do由Fi=g(Fi-1)順推後項;

            輸出順推結果Fn和順推過程;

        end; {else}

一、倒推法

    所謂倒推法,就是在不知初始值的情況下,經某種遞推關系而獲知問題的解或目标,再倒推過來,推知它的初始條件。因為這類問題的運算過程是一一映射的,故可分析得其遞推公式。然後再從這個解或目标出發,采用倒推手段,一步步地倒推到這個問題的初始陳述。

    下面舉例說明。

[例1] 貯油點

    一輛重型卡車欲穿過1000公裡的沙漠,卡車耗油為1升/公裡,卡車總載油能力為500公升。顯然卡車一次是過不了沙漠的。是以司機必須設法在沿途建立幾個儲油點,使卡車能順利穿越沙漠,試問司機如何建立這些儲油點?每一儲油點應存多少油,才能使卡車以消耗最少油的代價通過沙漠?

算法分析:

    程式設計計算及列印建立的貯油點序号,各貯油點距沙漠邊沿出發的距離以及存油量。

        No.        Distance(k.m.)        oil(litre)

        1                X X                X X

        2                X X                X X

        3                X X                X X

       ...              .....              ......

    設dis[i]   為第i個貯油點至終點(i=0)的距離;

      oil[i]   為第i個貯油點的存貯油量;

    我們可以用倒推法來解決這個問題。從終點向始點倒推,逐一求出每個貯油點的位置及存油量。

下圖表示倒推時的傳回點:

實用算法(基礎算法-遞推法-01)

    從貯油點i向貯油點i+1倒推的政策是,卡車在點i和點i+1間往返若幹次。卡車每次傳回i+1處時正好耗盡500公升汽油,而每次從i+1出發時又必須裝足500公升汽油。兩點之間的距離必須滿足在耗油最少的條件下使i點貯足i*500分升汽油的要求(0<=i<=n-1)。具體地講,第一個貯油點i=1應距終點i=0處500km且在該處貯藏500公升汽油,這樣才能保證卡車能由i=1處到達終點i=0處,這就是說

    dis[1]=500        oil[1]=500;

    為了在i=1處貯藏500公升汽油,卡車至少從i=2處開兩趟滿載油的車至i=1處。是以i=2處至少貯有2*500公升汽油,即oil[2]=500*2=1000。另外,再加上從i=1傳回至i=2處的一趟空載,合計往返3次。三次往返路程的耗油量按最省要求隻能為500公升。即d 12=500/3km

        dis[2]=dis[1]+d 12=dis[1]+500/3

實用算法(基礎算法-遞推法-01)

    為了在i=2處貯存1000公升汽油,卡車至少從i=3處開三趟滿載油的車至i=2處。報以i=3處至少貯有3*500公升汽油,即oil[3]=500*3=1500。加上i=2至i=3處的二趟返程空車,合計5次。路途耗油量也應為500公升,即d 23=500/5,

        dis[3]=dis[2]+d 23=dis[2]+500/5;

實用算法(基礎算法-遞推法-01)

    依此類推,為了在i=k處貯藏k*500公升汽油,卡車至少從i=k+1處開k趟滿載車至i=k處,即

    oil[k+1]=[k+1]*500=oil[k]+500,加上從i=k處傳回i=k+1的k-1趟返程空間,合計2k-1次。這2k-1次總耗油量按最省要求為500公升,即

    d k,k+1=500/(2k-1)

        dis[k+1]=dis[k]+d k,k+1

                =dis[k]+500/(2k-1);

實用算法(基礎算法-遞推法-01)

    最後,i=n至始點的距離為1000-dis[n],oil[n]=500*n。為了在i=n處取得n*500公升汽油,卡車至少從始點開n+1次滿載車至i=n,加上從i=n傳回始點的n趟返程空車,合計2n+1次,2n+1趟的總耗油量應正好為(1000-dis[n])*(2n+1),即始點藏油為oil[n]+(1000-dis[n])*(2n+1)。

轉換為C語言程式如下:

#include<stdio.h>

void main()

{

    int k;            

    float d,d1;      

    float oil[10],dis[10];

    int i;

    printf("NO. distance(k.m.)/toil(l.)/n");

    k=1;

    d=500;       

    dis[1]=500;

    oil[1]=500;

    do{

        k=k+1;

        d=d+500/(2*k-1);

        dis[k]=d;

        oil[k]=oil[k-1]+500;

    }while(!(d>=1000));

    dis[k]=1000;       

    d1=1000-dis[k-1];   

    oil[k]=d1*(2*k+1)+oil[k-1];   

    for(i=0;i<k;i++)      

        printf("%d/t%f/t%f/t/n",i,1000-dis[k-i],oil[k-i]);

}

繼續閱讀