軟件設(shè)計(jì)師專題_算法分析與設(shè)計(jì)_[文檔在線提供]_第1頁
軟件設(shè)計(jì)師專題_算法分析與設(shè)計(jì)_[文檔在線提供]_第2頁
軟件設(shè)計(jì)師專題_算法分析與設(shè)計(jì)_[文檔在線提供]_第3頁
軟件設(shè)計(jì)師專題_算法分析與設(shè)計(jì)_[文檔在線提供]_第4頁
軟件設(shè)計(jì)師專題_算法分析與設(shè)計(jì)_[文檔在線提供]_第5頁
已閱讀5頁,還剩13頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

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

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

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

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

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

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

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

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

9、#160;                    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”);              具體使用迭代法求根時(shí)應(yīng)注意以下兩種可能發(fā)生的情況:(1)如果方程無解,算法求出的近似根序列就不會(huì)收斂,迭代過程會(huì)變成死循環(huán),因此在使用迭代算法前應(yīng)先考察方程是否有解,并在程序中對(duì)迭代的次數(shù)給予限制;(2

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

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

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

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

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

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

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

19、#160;                               if (e=a)|(e=b)|(e=c)|(e=d) continue;f=21-(a+b+c+d+e);/最后一個(gè)用減法算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、#160;                                                  

22、                                                   

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

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

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

26、)!連續(xù)累加k-1次后求得。例如,已知4!=24,計(jì)算5!,可對(duì)原來的24累加4次24后得到120。細(xì)節(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&l

28、t;=m;i+)/i存放的是整數(shù)的位數(shù)                    r=(i<a0?ai+bi:ai)+carry;/進(jìn)位標(biāo)志                       ai=r%1

29、0;                      carry=r/10;                            if

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

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

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

33、);                write(a,k);/輸出長(zhǎng)整數(shù)的各位                getchar();       1.4 遞歸法      遞歸是設(shè)計(jì)和描述算法的

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

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

36、160; (當(dāng)n>1時(shí))。寫成遞歸函數(shù)有: int fib(int n)      if (n=0)        return  0;      if (n=1)        return  1;      if (n>1) 

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

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

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

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

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

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

43、60;           else                     /*又一個(gè)完整方案,因?yàn)樗惹懊娴姆桨负?,以它作為最佳方?/以當(dāng)前方案作為臨時(shí)最佳方案保存;          

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

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

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

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

48、的解。如能判定某個(gè)查找分支不會(huì)找到更好的解,算法不會(huì)在該分支繼續(xù)查找,而是立即終止該分支,并去考察下一個(gè)分支。    Try(物品號(hào),總重,價(jià)值)按上述算法編寫函數(shù)和程序如下:【程序】# 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包含在當(dāng)前方案中的可能性*/       if (tw+ai.weight<=limitW)          

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

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

53、0;     maxv=tv;                            copi=0;       /*考慮物品i不包含在當(dāng)前方案中的可能性*/       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(“輸入物品種數(shù)n”);  

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

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

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

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

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

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

63、;              double     value;                     aN;int    k,n;struct    

64、60;      int          flg;                        double     tw;       

65、;                 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 (tot

67、v=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、60;    if (i<n-1)                                             

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

73、60;    i+;                                              

74、0;                                     else             

75、;                                  maxv=tv;                &

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

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

78、;                                                  

79、0;                   break;                     case 0:    i-;     

80、60;                             break;                     d

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

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

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

84、;                                    i+;              &

85、#160;                                                  

86、                   else                                

87、               maxv=tv-ai.value;                                  

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

89、60;                       copk=twvk.flg!=0;                        

90、60;                                                  &#

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

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

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

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

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

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

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

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

99、#160;       從已用的第一只箱子開始順序?qū)ふ夷芊湃胛锲穒 的箱子j;              if (已用箱子都不能再放物品i)                   另用一個(gè)箱子j,并將物品i放入該箱子;   

100、;                  box_count+;                            else    

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

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

103、nt  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;       P

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

106、intf(“請(qǐng)按體積從大到小順序輸入各物品的體積:”);       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、0;        p=(ELE *)malloc(sizeof(ELE);              p->vno=i;              for (j=box_h;j!=NULL;j=j->next)    

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

109、;       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、60;      for (q=j->next;q!=NULL&&q->link!=NULL;q=q->link);              if (q=NULL)                   p->

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

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

116、0;                      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、60;       printf(“%4d”,p->vno+1);              printf(“n”);       1.6 分治法1分治法的基本思想任何一個(gè)可以用計(jì)算機(jī)求解的問題所需的計(jì)算時(shí)間都與其規(guī)模N有關(guān)。問題的規(guī)模越小,越容易直接求解,解題所需的計(jì)算時(shí)間也越少。例如,對(duì)于n個(gè)元素的排序問題,當(dāng)n=1時(shí),不需任何計(jì)算;n=

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

溫馨提示

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

評(píng)論

0/150

提交評(píng)論