專題十算法分析與設計_第1頁
專題十算法分析與設計_第2頁
專題十算法分析與設計_第3頁
專題十算法分析與設計_第4頁
專題十算法分析與設計_第5頁
已閱讀5頁,還剩13頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、專題十:算法分析與設計1常用的算法設計方法:1.1 迭代法1.2 窮舉搜索法1.3 遞推法1.4 遞歸法1.5 貪婪法1.6 分治法1.7 動態(tài)規(guī)劃法1.8 回溯法算法基礎部分:算法是對特定問題求解步驟的一種描述,算法是指令的有限序列,其中每一條指令表示一個或多個操作。算法具有以下5個屬性:有窮性:一個算法必須總是在執(zhí)行有窮步之后結束,且每一步都在有窮時間內完成。確定性:算法中每一條指令必須有確切的含義。不存在二義性。只有一個入口和一個出口可行性:一個算法是可行的就是算法描述的操作是可以通過已經實現的基本運算執(zhí)行有限次來實現的。輸入:一個算法有零個或多個輸入,這些輸入取自于某個特定對象的集合。

2、輸出:一個算法有一個或多個輸出,這些輸出同輸入有著某些特定關系的量。所以對應的算法設計的要求:正確性:算法應滿足具體問題的需求;可讀性:算法應該好讀,以有利于讀者對程序的理解;健壯性:算法應具有容錯處理,當輸入為非法數據時,算法應對其作出反應,而不是產生莫名其妙的輸出結果。效率與存儲量需求:效率指的是算法執(zhí)行的時間;存儲量需求指算法執(zhí)行過程中所需要的最大存儲空間。一般這兩者與問題的規(guī)模有關。1.1  迭代法:迭代法是用于求方程或方程組近似根的一種常用的算法設計方法。設方程為f(x)=0,用某種數學方法導出等價的形式x=g(x),然后按以下步驟執(zhí)行:(1)選一個方程的近似根,賦給變量x

3、0;(2)將x0的值保存于變量x1,然后計算g(x1),并將結果存于變量x0;(3)當x0與x1的差的絕對值還小于指定的精度要求時,重復步驟(2)的計算。若方程有根,并且用上述方法計算出來的近似根序列收斂,則按上述方法求得的x0就認為是方程的根。上述算法用C程序的形式表示為:【算法】迭代法求方程的根     x0=初始近似根;       do               x1

4、=x0;              x0=g(x1);    /*按特定的方程計算新的近似根*/              while ( fabs(x0-x1)>Epsilon);       printf(“方程的近似根是%fn”,x0);

5、迭代算法也常用于求方程組的根,令              X=(x0,x1,xn-1)設方程組為:              xi=gi(X)         (I=0,1,n-1)則求方程組根的迭代算法可描述如下:【算法】迭代法求方程組的根 &#

6、160;         for (i=0;i<n;i+)                     xi=初始近似根;              do    

7、60;                 for (i=0;i<n;i+)                            yi=xi;  

8、                   for (i=0;i<n;i+)                            xi=gi(X);

9、                     for (delta=0.0,i=0;i<n;i+)if (fabs(yi-xi)>delta)        delta=fabs(yi-xi);          

10、;           while (delta>Epsilon);              for (i=0;i<n;i+)                   &

11、#160; printf(“變量x%d的近似根是 %f”,I,xi);              printf(“n”);              具體使用迭代法求根時應注意以下兩種可能發(fā)生的情況:(1)如果方程無解,算法求出的近似根序列就不會收斂,迭代過程會變成死循環(huán),因此在使用迭代算法前應先考察方程是否有解,并在程序中對迭代的次數給予限制;(

12、2)方程雖然有解,但迭代公式選擇不當,或迭代的初始近似根選擇不合理,也會導致迭代失敗。1.2 窮舉搜索法:窮舉搜索法是對可能是解的眾多候選解按某種順序進行逐一枚舉和檢驗,并從中找出那些符合要求的候選解作為問題的解。要解決的問題只有有限種可能,在沒有更好算法時總可以用窮舉搜索的辦法解決,即逐個的檢查所有可能的情況。可以想象,情況較多時這種方法極為費時。實際上并不需要機械的檢查每一種情況,常常是可以提前判斷出某些情況不可能取到最優(yōu)解,從而可以提前舍棄這些情況。這樣也是隱含的檢查了所有可能的情況,既減少了搜索量,又保證了不漏掉最優(yōu)解?!締栴}】 將A、B、C、D、E、F這六個變量排成如圖所示

13、的三角形,這六個變量分別取1,6上的整數,且均不相同。求使三角形三條邊上的變量之和相等的全部解。如圖就是一個解。程序引入變量a、b、c、d、e、f,并讓它們分別順序取1至6的整數,在它們互不相同的條件下,測試由它們排成的如圖所示的三角形三條邊上的變量之和是否相等,如相等即為一種滿足要求的排列,把它們輸出。當這些變量取盡所有的組合后,程序就可得到全部可能的解。細節(jié)見下面的程序。# include <stdio.h>void main()     int a,b,c,d,e,f;     

14、0; for (a=1;a<=6;a+)    /a,b,c,d,e依次取不同的值                 for (b=1;b<=6;b+)                     

15、60;             if (b=a)        continue;                     for (c=1;c<=6;c+)    

16、;                                      if (c=a)|(c=b)    continue;      

17、60;                     for (d=1;d<=6;d+)                           

18、;                      if (d=a)|(d=b)|(d=c)      continue;for (e=1;e<=6;e+)                 

19、                                if (e=a)|(e=b)|(e=c)|(e=d) continue;f=21-(a+b+c+d+e);/最后一個用減法算if (a+b+c=c+d+e)&&(a+b+c=e+f+a)  

20、 printf(“%6d,a);       printf(“%4d%4d”,b,f);       printf(“%2d%4d%4d”,c,d,e);       scanf(“%c”);                   

21、                                                   

22、;                                                   

23、60;                  按窮舉法編寫的程序通常不能適應變化的情況。如問題改成有9個變量排成三角形,每條邊有4個變量的情況,程序的循環(huán)重數就要相應改變,循環(huán)的重數和變量的個數相關。從上述問題解決的方法中,最重要的因素就是確定某種方法來確定所有的候選解。下1.3 遞推法:      遞推法是利用問題本身所具有的一種遞推關系求問題解的一種方法。設要求問題規(guī)模為N的解,當N=1時,解或為

24、已知,或能非常方便地得到解。能采用遞推法構造算法的問題有重要的遞推性質,即當得到問題規(guī)模為i-1的解后,由問題的遞推性質,能從已求得的規(guī)模為1,2,i-1的一系列解,構造出問題規(guī)模為I的解。這樣,程序可從i=0或i=1出發(fā),重復地,由已知至i-1規(guī)模的解,通過遞推,獲得規(guī)模為i的解,直至得到規(guī)模為N的解。【問題】 階乘計算問題描述:編寫程序,對給定的n(n100),計算并輸出k的階乘k?。╧=1,2,n)的全部有效數字。由于要求的整數可能大大超出一般整數的位數,程序用一維數組存儲長整數,存儲長整數數組的每個元素只存儲長整數的一位數字。如有m位成整數N用數組a 存儲: 

25、60;     N=am×10m-1+am-1×10m-2+ +a2×101+a1×100并用a0存儲長整數N的位數m,即a0=m。按上述約定,數組的每個元素存儲k的階乘k!的一位數字,并從低位到高位依次存于數組的第二個元素、第三個元素。例如,5!=120,在數組中的存儲形式為:3021     首元素3表示長整數是一個3位數,接著是低位到高位依次是0、2、1,表示成整數120。     計算階乘k!可采用對已求得的階乘(k-

26、1)!連續(xù)累加k-1次后求得。例如,已知4!=24,計算5!,可對原來的24累加4次24后得到120。細節(jié)見以下程序。# include <stdio.h># include <malloc.h># define  MAXN   1000void  pnext(int a ,int k)/已知a中的(k-1)!,求出k!在a中。     int *b,m=a0,i,j,r,carry;       b=(int * ) malloc

27、(sizeof(int)* (m+1);       for ( i=1;i<=m;i+)        bi=ai;       for ( j=1;j<k;j+)     /控制累加k-1次            for ( carry=0,i=1;i&

28、lt;=m;i+)/i存放的是整數的位數                    r=(i<a0?ai+bi:ai)+carry;/進位標志                       ai=r%

29、10;                      carry=r/10;                            i

30、f (carry)  a+m=carry;              free(b);       a0=m;void  write(int *a,int k)/功能是輸出累加K次后的數組的各個位     int i;       printf(“%4d!=”,k);  

31、0;    for (i=a0;i>0;i-)              printf(“%d”,ai);printf(“nn”);void main()     int aMAXN,n,k;       printf(“Enter the number n:  “);    

32、60;  scanf(“%d”,&n);       a0=1;       a1=1;       write(a,1);       for (k=2;k<=n;k+)              pnext(a,

33、k);                write(a,k);/輸出長整數的各位                getchar();       1.4 遞歸法      遞歸是設計和描述算法

34、的一種有力的工具,由于它在復雜算法的描述中被經常采用,為此在進一步介紹其他算法設計方法之前先討論它。      能采用遞歸描述的算法通常有這樣的特征:為求解規(guī)模為N的問題,設法將它分解成規(guī)模較小的問題,然后從這些小問題的解方便地構造出大問題的解,并且這些規(guī)模較小的問題也能采用同樣的分解和綜合方法,分解成規(guī)模更小的問題,并從這些更小問題的解構造出規(guī)模較大問題的解。特別地,當規(guī)模N=1時,能直接得解。【問題】編寫計算斐波那契(Fibonacci)數列的第n項函數fib(n)。斐波那契數列為:0、1、1、2、3、,即:  

35、0;           fib(0)=0;              fib(1)=1;              fib(n)=fib(n-1)+fib(n-2)      &

36、#160; (當n>1時)。寫成遞歸函數有: int fib(int n)      if (n=0)        return  0;      if (n=1)        return  1;      if (n>1) 

37、60;       return  fib(n-1)+fib(n-2);    遞歸算法的執(zhí)行過程分遞推和回歸兩個階段。在遞推階段,把較復雜的問題(規(guī)模為n)的求解推到比原問題簡單一些的問題(規(guī)模小于n)的求解。例如上例中,求解fib(n),把它推到求解fib(n-1)和fib(n-2)。也就是說,為計算fib(n),必須先計算fib(n-1)和fib(n-2),而計算fib(n-1)和fib(n-2),又必須先計算fib(n-3)和fib(n-4)。依次類推,直至計算fib(1)和f

38、ib(0),分別能立即得到結果1和0。在遞推階段,必須要有終止遞歸的情況。例如在函數fib中,當n為1和0的情況。    在回歸階段,當獲得最簡單情況的解后,逐級返回,依次得到稍復雜問題的解,例如得到fib(1)和fib(0)后,返回得到fib(2)的結果,在得到了fib(n-1)和fib(n-2)的結果后,返回得到fib(n)的結果。    在編寫遞歸函數時要注意,函數中的局部變量和參數只是局限于當前調用層,當遞推進入“簡單問題”層時,原來層次上的參數和局部變量便被隱蔽起來。在一系列“簡單問題”層,它們各有自己的參數和局部

39、變量。     由于遞歸引起一系列的函數調用,并且可能會有一系列的重復計算,遞歸算法的執(zhí)行效率相對較低。當某個遞歸算法能較方便地轉換成遞推算法時,通常按遞推算法編寫程序。例如上例計算斐波那契數列的第n項的函數fib(n)應采用遞推算法,即從斐波那契數列的前兩項出發(fā),逐次由前兩項計算出下一項,直至計算出要求的第n項?!締栴}】背包問題問題描述:有不同價值、不同重量的物品n件,求從這n件物品中選取一部分物品的選擇方案,使選中物品的總重量不超過指定的限制重量,但選中物品的價值之和最大。設n件物品的重量分別為w0、w1、wn-1,物品的價值分別為v0、v1、vn-

40、1。采用遞歸尋找物品的選擇方案。設前面已有了多種選擇的方案,并保留了其中總價值最大的方案于數組option ,該方案的總價值存于變量maxv。當前正在考察新方案,其物品選擇情況保存于數組cop 。假定當前方案已考慮了前i-1件物品,現在要考慮第i件物品;當前方案已包含的物品的重量之和為tw;至此,若其余物品都選擇是可能的話,本方案能達到的總價值的期望值為tv。算法引入tv是當一旦當前方案的總價值的期望值也小于前面方案的總價值maxv時,繼續(xù)考察當前方案變成無意義的工作,應終止當前方案,立即去考察下一個方案。因為當方案的總價值不比maxv大時,該方案不會被再考察,這同時保證函數后找到的方案一定會

41、比前面的方案更好。對于第i件物品的選擇考慮有兩種可能:(1)考慮物品i被選擇,這種可能性僅當包含它不會超過方案總重量限制時才是可行的。選中后,繼續(xù)遞歸去考慮其余物品的選擇。(2)考慮物品i不被選擇,這種可能性僅當不包含物品i也有可能會找到價值更大的方案的情況。按以上思想寫出遞歸算法如下:try(物品i,當前選擇已達到的重量和,本方案可能達到的總價值tv)     /*考慮物品i包含在當前方案中的可能性*/       if(包含物品i是可以接受的)    

42、        將物品i包含在當前方案中;              if (i<n-1)                     try(i+1,tw+物品i的重量,tv);  &#

43、160;           else                     /*又一個完整方案,因為它比前面的方案好,以它作為最佳方案*/以當前方案作為臨時最佳方案保存;          

44、60;          恢復物品i不包含狀態(tài);                            /*考慮物品i不包含在當前方案中的可能性*/        

45、60;     if (不包含物品i僅是可考慮的)                     if (i<n-1)                    &

46、#160;       try(i+1,tw,tv-物品i的價值);                     else                  

47、60;         /*又一個完整方案,因它比前面的方案好,以它作為最佳方案*/以當前方案作為臨時最佳方案保存;              為了理解上述算法,特舉以下實例。設有4件物品,它們的重量和價值見表:物品0123重量5321價值4431      并設限制重量為7。則按以上算法,下圖表示找解過程。由圖知,一旦找到一個解,算法就進一步找更

48、好的解。如能判定某個查找分支不會找到更好的解,算法不會在該分支繼續(xù)查找,而是立即終止該分支,并去考察下一個分支。    Try(物品號,總重,價值)按上述算法編寫函數和程序如下:【程序】# include <stdio.h># define   N     100double     limitW,totV,maxV;int    optionN,copN;struct    

49、;          double     weight;                     double     value;         

50、;    aN;int    n;void find(int i,double tw,double tv)     int k;       /*考慮物品i包含在當前方案中的可能性*/       if (tw+ai.weight<=limitW)          

51、60; copi=1;              if (i<n-1) find(i+1,tw+ai.weight,tv);              else               &#

52、160;   for (k=0;k<n;k+)                            optionk=copk;               

53、60;     maxv=tv;                            copi=0;       /*考慮物品i不包含在當前方案中的可能性*/       if

54、(tv-ai.value>maxV)              if (i<n-1) find(i+1,tw,tv-ai.value);              else             

55、      for (k=0;k<n;k+)                            optionk=copk;             &

56、#160;       maxv=tv-ai.value;               void main()     int k;       double w,v;       printf(“輸入物品種數n”);  

57、;     scanf(“%d”,&n);       printf(“輸入各物品的重量和價值n”);       for (totv=0.0,k=0;k<n;k+)            scanf(“%1f%1f”,&w,&v);      &#

58、160;       ak.weight=w;              ak.value=v;              totV+=V;            

59、60; printf(“輸入限制重量n”);       scanf(“%1f”,&limitV);       maxv=0.0;       for (k=0;k<n;k+)  copk=0;       find(0,0.0,totV);       for (k=0;

60、k<n;k+)              if (optionk)   printf(“%4d”,k+1);       printf(“n總價值為%.2fn”,maxv);作為對比,下面以同樣的解題思想,考慮非遞歸的程序解。為了提高找解速度,程序不是簡單地逐一生成所有候選解,而是從每個物品對候選解的影響來形成值得進一步考慮的候選解,一個候選解是通過依次考察每個物品形成的。對物品i

61、的考察有這樣幾種情況:1   當該物品被包含在候選解中依舊滿足解的總重量的限制,該物品被包含在候選解中是應該繼續(xù)考慮的;2   反之,該物品不應該包括在當前正在形成的候選解中。3   僅當物品不被包括在候選解中,還是有可能找到比目前臨時最佳解更好的候選解時,才去考慮該物品不被包括在候選解中;4   該物品不包括在當前候選解中的方案也不應繼續(xù)考慮。5   對于任意一個值得考慮的餓方案,程序就去進一步考慮下一個物品;【程序】# include <stdio.h># define 

62、;  N     100double     limitW;int    copN;struct      ele        double     weight;             

63、0;              double     value;                     aN;int    k,n;struct    &#

64、160;      int          flg;                        double     tw;      

65、0;                 double     tv;              twvN;void next(int i,double tw,double tv)     twvi.flg=1;  

66、;     twvi.tw=tw;       twvi.tv=tv;double find(struct ele *a,int n)     int i,k,f;       double maxv,tw,tv,totv;       maxv=0;       for (to

67、tv=0.0,k=0;k<n;k+)              totv+=ak.value;       next(0,0.0,totv);       i=0;       While (i>=0)       &

68、#160;    f=twvi.flg;              tw=twvi.tw;              tv=twvi.tv;              switch

69、(f)                   case 1:    twvi.flg+;                          &

70、#160;        if (tw+ai.weight<=limitW)                                     &#

71、160;    if (i<n-1)                                             

72、;  next(i+1,tw+ai.weight,tv);                                            &#

73、160;    i+;                                              

74、60;                                     else            

75、0;                                  maxv=tv;                

76、                                 for (k=0;k<n;k+)              

77、0;                                         copk=twvk.flg!=0;      

78、0;                                                  

79、60;                   break;                     case 0:    i-;     &#

80、160;                             break;                    

81、default:    twvi.flg=0;                                   if (tv-ai.value>maxv)     

82、60;                                    if (i<n-1)            &

83、#160;                                  next(i+1,tw,tv-ai.value);            

84、0;                                    i+;              

85、                                                   

86、;                   else                                

87、;               maxv=tv-ai.value;                                 

88、0;               for (k=0;k<n;k+)                                &#

89、160;                       copk=twvk.flg!=0;                        &#

90、160;                                                  &

91、#160; break;                            return maxv;void main()     double maxv;       printf(“輸入物品種數n”);   &#

92、160;   scanf(“%d”,&n);       printf(“輸入限制重量n”);       scanf(“%1f”,&limitW);printf(“輸入各物品的重量和價值n”);       for (k=0;k<n;k+)           &#

93、160;  scanf(“%1f%1f”,&ak.weight,&ak.value);       maxv=find(a,n);       printf(“n選中的物品為n”);for (k=0;k<n;k+)              if (optionk)   printf(“%4d”,

94、k+1);       printf(“n總價值為%.2fn”,maxv);1.5 貪婪法      貪心法是求解關于獨立系統(tǒng)組合優(yōu)化問題的一種簡單算法,求最小生成樹的Kruskal算法就是一種貪心算法。貪心法的基本思路是:從問題的某一個初始解出發(fā)逐步逼近給定的目標,以盡可能快的地求得更好的解。當達到某算法中的某一步不能再繼續(xù)前進時,算法停止。 該算法存在問題: 1. 不能保證求得的最后解是最佳的; 2. 不能用來求最大或最小解問題; 3. 只能求滿足某些約束條件的可行解的范圍。 實現

95、該算法的過程: 從問題的某一初始解出發(fā); while 能朝給定總目標前進一步 do 求出可行解的一個解元素; 由所有解元素組合成問題的一個可行解;貪婪法是一種不追求最優(yōu)解,只希望得到較為滿意解的方法。貪婪法一般可以快速得到滿意的解,因為它省去了為找最優(yōu)解要窮盡所有可能而必須耗費的大量時間。貪婪法常以當前情況為基礎作最優(yōu)選擇,而不考慮各種可能的整體情況,所以貪婪法不要回溯。      例如平時購物找錢時,為使找回的零錢的硬幣數最少,不考慮找零錢的所有各種發(fā)表方案,而是從最大面值的幣種開始,按遞減的順序考慮各幣種,先盡量用大面值的幣種,當不足大面值

96、幣種的金額時才去考慮下一種較小面值的幣種。這就是在使用貪婪法。這種方法在這里總是最優(yōu),是因為銀行對其發(fā)行的硬幣種類和硬幣面值的巧妙安排。如只有面值分別為1、5和11單位的硬幣,而希望找回總額為15單位的硬幣。按貪婪算法,應找1個11單位面值的硬幣和4個1單位面值的硬幣,共找回5個硬幣。但最優(yōu)的解應是3個5單位面值的硬幣?!締栴}】裝箱問題問題描述:裝箱問題可簡述如下:設有編號為0、1、n-1的n種物品,體積分別為v0、v1、vn-1。將這n種物品裝到容量都為V的若干箱子里。約定這n種物品的體積均不超過V,即對于0in,有0viV。不同的裝箱方案所需要的箱子數目可能不同。裝箱問題要求使裝盡這n種物

97、品的箱子數要少。    若考察將n種物品的集合分劃成n個或小于n個物品的所有子集,最優(yōu)解就可以找到。但所有可能劃分的總數太大。對適當大的n,找出所有可能的劃分要花費的時間是無法承受的。為此,對裝箱問題采用非常簡單的近似算法,即貪婪法。該算法依次將物品放到它第一個能放進去的箱子中,該算法雖不能保證找到最優(yōu)解,但還是能找到非常好的解。不失一般性,設n件物品的體積是按從大到小排好序的,即有v0v1vn-1。如不滿足上述要求,只要先對這n件物品按它們的體積從大到小排序,然后按排序結果對物品重新編號即可。裝箱算法簡單描述如下:   &

98、#160; 輸入箱子的容積;       輸入物品種數n;       按體積從大到小順序,輸入各物品的體積;       預置已用箱子鏈為空;       預置已用箱子計數器box_count為0;       for (i=0;i<n;i+)    

99、        從已用的第一只箱子開始順序尋找能放入物品i 的箱子j;              if (已用箱子都不能再放物品i)                   另用一個箱子j,并將物品i放入該箱子;  

100、0;                  box_count+;                            else   

101、0;                 將物品i放入箱子j;             上述算法能求出需要的箱子數box_count,并能求出各箱子所裝物品。下面的例子說明該算法不一定能找到最優(yōu)解,設有6種物品,它們的體積分別為:60、45、35、20、20和20單位體積,箱子的容積為100個單位體積。按上述算法計算,需三只箱子,各

102、箱子所裝物品分別為:第一只箱子裝物品1、3;第二只箱子裝物品2、4、5;第三只箱子裝物品6。而最優(yōu)解為兩只箱子,分別裝物品1、4、5和2、3、6。      若每只箱子所裝物品用鏈表來表示,鏈表首結點指針存于一個結構中,結構記錄尚剩余的空間量和該箱子所裝物品鏈表的首指針。另將全部箱子的信息也構成鏈表。以下是按以上算法編寫的程序。【程序】# include <stdio.h># include <stdlib.h>typedef  struct  ele    

103、int  vno;       struct  ele  *link;     ELE;typedef  struct  hnode     int  remainder;       ELE  *head;       Struct  hnode 

104、 *next;     HNODE;void  main()     int  n, i, box_count, box_volume, *a;       HNODE  *box_h,  *box_t,  *j;       ELE   *p,  *q;      

105、Printf(“輸入箱子容積n”);       Scanf(“%d”,&box_volume);       Printf(“輸入物品種數n”);       Scanf(“%d”,&n);       A=(int *)malloc(sizeof(int)*n);       P

106、rintf(“請按體積從大到小順序輸入各物品的體積:”);       For (i=0;i<n;i+)    scanf(“%d”,a+i);       Box_h=box_t=NULL;       Box_count=0;       For (i=0;i<n;i+)   

107、60;        p=(ELE *)malloc(sizeof(ELE);              p->vno=i;              for (j=box_h;j!=NULL;j=j->next)    

108、60;                if (j->remainder>=ai)   break;              if (j=NULL)           

109、0;       j=(HNODE *)malloc(sizeof(HNODE);                     j->remainder=box_volume-ai;              

110、;       j->head=NULL;                     if (box_h=NULL)        box_h=box_t=j;         

111、;            else  box_t=boix_t->next=j;                     j->next=NULL;           

112、;          box_count+;                            else  j->remainder-=ai;       &#

113、160;      for (q=j->next;q!=NULL&&q->link!=NULL;q=q->link);              if (q=NULL)                   p->

114、;link=j->head;                     j->head=p;                         

115、0;  else                   p->link=NULL;                     q->link=p;     

116、60;                      printf(“共使用了%d只箱子”,box_count);       printf(“各箱子裝物品情況如下:”);       for (j=box_h,i=1;j!=NULL;j=j->next,i+)  &

117、#160;         printf(“第%2d只箱子,還剩余容積%4d,所裝物品有;n”,I,j->remainder);              for (p=j->head;p!=NULL;p=p->link)             &#

118、160;       printf(“%4d”,p->vno+1);              printf(“n”);       1.6 分治法1分治法的基本思想任何一個可以用計算機求解的問題所需的計算時間都與其規(guī)模N有關。問題的規(guī)模越小,越容易直接求解,解題所需的計算時間也越少。例如,對于n個元素的排序問題,當n=1時,不需任何計算;n

119、=2時,只要作一次比較即可排好序;n=3時只要作3次比較即可,。而當n較大時,問題就不那么容易處理了。要想直接解決一個規(guī)模較大的問題,有時是相當困難的。分治法的設計思想是,將一個難以直接解決的大問題,分割成一些規(guī)模較小的相同問題,以便各個擊破,分而治之。如果原問題可分割成k個子問題(1<kn),且這些子問題都可解,并可利用這些子問題的解求出原問題的解,那么這種分治法就是可行的。由分治法產生的子問題往往是原問題的較小模式,這就為使用遞歸技術提供了方便。在這種情況下,反復應用分治手段,可以使子問題與原問題類型一致而其規(guī)模卻不斷縮小,最終使子問題縮小到很容易直接求出其解。這自然導致遞歸過程的產生。分治與遞歸像一對孿生兄弟,經常同時應用在算法設計之中,并由此產生許多高效算法。2分治法的適用條件分治法所能解決的問題一般具有以下幾個特征:(1)該問題的規(guī)??s小到一定的程度就可以容易地解決;(2)該問題可以分解為若干個規(guī)模較小的相同問題,即該問題具有最優(yōu)子結構性質;(3)利用該問題分解出的子問題的解可以合并為該問題的解;(4)該問題所分解出的各個子問題是相互獨立的,即子問題之間不包含公共的子問題。 第一條特征是絕大多數問題都可以滿足的,因為問題的計算復雜性一般是隨著問題規(guī)模的增加而增加;第二條特征是應用分治法的前提,它也是

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論