黄色在线观看视频-黄色在线免费看-黄色在线视频免费-黄色在线视频免费看-免费啪啪网-免费啪啪网站

查看全部128種考試
1
2
3
4
5
6
7
8
9
10
xihuyu2000  
【字體: 常用算法設計方法
常用算法設計方法
djks.exam8.com 來源:老頑童 更新:2005-4-20 17:27:00 計算機等級考試 考試論壇

【問題】       馬的遍歷

    問題描述:在8×8方格的棋盤上,從任意指定的方格出發,為馬尋找一條走遍棋盤每一格并且只經過一次的一條路徑。

       馬在某個方格,可以在一步內到達的不同位置最多有8個,如圖所示。如用二維數組board[ ][ ]表示棋盤,其元素記錄馬經過該位置時的步驟號。另對馬的8種可能走法(稱為著法)設定一個順序,如當前位置在棋盤的(ij)方格,下一個可能的位置依次為(i+2j+1)、(i+1j+2)、(i-1j+2)、(i-2j+1)、(i-2j-1)、(i-1j-2)、(i+1j-2)、(i+2j-1),實際可以走的位置盡限于還未走過的和不越出邊界的那些位置。為便于程序的同意處理,可以引入兩個數組,分別存儲各種可能走法對當前位置的縱橫增量。

 

4

 

3

 

5

 

 

 

2

 

 

 

 

6

 

 

 

1

 

7

 

0

 

 

       對于本題,一般可以采用回溯法,這里采用Warnsdoff策略求解,這也是一種貪婪法,其選擇下一出口的貪婪標準是在那些允許走的位置中,選擇出口最少的那個位置。如馬的當前位置(ij)只有三個出口,他們是位置(i+2j+1)、(i-2j+1)和(i-1j-2),如分別走到這些位置,這三個位置又分別會有不同的出口,假定這三個位置的出口個數分別為423,則程序就選擇讓馬走向(i-2j+1)位置。

       由于程序采用的是一種貪婪法,整個找解過程是一直向前,沒有回溯,所以能非常快地找到解。但是,對于某些開始位置,實際上有解,而該算法不能找到解。對于找不到解的情況,程序只要改變8種可能出口的選擇順序,就能找到解。改變出口選擇順序,就是改變有相同出口時的選擇標準。以下程序考慮到這種情況,引入變量start,用于控制8種可能著法的選擇順序。開始時為0,當不能找到解時,就讓start1,重新找解。細節以下程序。

【程序】

# include <stdio.h>

int delta_i[ ]={2,1,-1,-2,-2,-1,1,2};

int delta_j[ ]={1,2,2,1,-1,-2,-2,-1};

int board[8][8];

int exitn(int i,int j,int s,int a[ ])

{     int i1,j1,k,count;

       for (count=k=0;k<8;k++)

       {     i1=i+delta_i[(s+k)%8];

              j1=i+delta_j[(s+k)%8];

              if (i1>=0&&i1<8&&j1>=0&&j1<8&&board[I1][j1]==0)

                     a[count++]=(s+k)%8;

       }

       return count;

}

 

int next(int i,int j,int s)

{     int m,k,mm,min,a[8],b[8],temp;

       m=exitn(i,j,s,a);

       if (m==0)              return –1;

       for (min=9,k=0;k<m;k++)

       {     temp=exitn(I+delta_i[a[k]],j+delta_j[a[k]],s,b);

              if (temp<min)

              {     min=temp;

kk=a[k];

              }

       }

       return  kk;

}

 

void main()

{     int sx,sy,i,j,step,no,start;

       for (sx=0;sx<8;sx++)

       for (sy=0;sy<8;sy++)

       {     start=0;

              do {

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

                            for (j=0;j<8;j++)

                                   board[i][j]=0;

                     board[sx][sy]=1;

                     I=sx;       j=sy;

                     For (step=2;step<64;step++)

                     {     if ((no=next(i,j,start))==-1)   break;

                            I+=delta_i[no];

                            j+=delta_j[no];

                            board[i][j]=step;

                     }

                     if (step>64)    break;

                     start++;

              } while(step<=64)

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

              {     for (j=0;j<8;j++)

                            printf(“%4d”,board[i][j]);

                     printf(“\n\n”);

              }

              scanf(“%*c”);

       }

}

七、分治法

1、分治法的基本思想

    任何一個可以用計算機求解的問題所需的計算時間都與其規模N有關。問題的規模越小,越容易直接求解,解題所需的計算時間也越少。例如,對于n個元素的排序問題,當n=1時,不需任何計算;n=2時,只要作一次比較即可排好序;n=3時只要作3次比較即可,…。而當n較大時,問題就不那么容易處理了。要想直接解決一個規模較大的問題,有時是相當困難的。

    分治法的設計思想是,將一個難以直接解決的大問題,分割成一些規模較小的相同問題,以便各個擊破,分而治之。

    如果原問題可分割成k個子問題(1<kn),且這些子問題都可解,并可利用這些子問題的解求出原問題的解,那么這種分治法就是可行的。由分治法產生的子問題往往是原問題的較小模式,這就為使用遞歸技術提供了方便。在這種情況下,反復應用分治手段,可以使子問題與原問題類型一致而其規模卻不斷縮小,最終使子問題縮小到很容易直接求出其解。這自然導致遞歸過程的產生。分治與遞歸像一對孿生兄弟,經常同時應用在算法設計之中,并由此產生許多高效算法。

2、分治法的適用條件

    分治法所能解決的問題一般具有以下幾個特征:

1)該問題的規模縮小到一定的程度就可以容易地解決;

2)該問題可以分解為若干個規模較小的相同問題,即該問題具有最優子結構性質

3)利用該問題分解出的子問題的解可以合并為該問題的解;

4)該問題所分解出的各個子問題是相互獨立的,即子問題之間不包含公共的子子問題。

    上述的第一條特征是絕大多數問題都可以滿足的,因為問題的計算復雜性一般是隨著問題規模的增加而增加;第二條特征是應用分治法的前提,它也是大多數問題可以滿足的,此特征反映了遞歸思想的應用;第三條特征是關鍵,能否利用分治法完全取決于問題是否具有第三條特征,如果具備了第一條和第二條特征,而不具備第三條特征,則可以考慮貪心法或動態規劃法。第四條特征涉及到分治法的效率,如果各子問題是不獨立的,則分治法要做許多不必要的工作,重復地解公共的子問題,此時雖然可用分治法,但一般用動態規劃法較好。

3、分治法的基本步驟

    分治法在每一層遞歸上都有三個步驟:

1)分解:將原問題分解為若干個規模較小,相互獨立,與原問題形式相同的子問題;

2)解決:若子問題規模較小而容易被解決則直接解,否則遞歸地解各個子問題;

3)合并:將各個子問題的解合并為原問題的解。

    它的一般的算法設計模式如下:

Divide_and_ConquerP

if |P|n0

then returnADHOCP))

P分解為較小的子問題P1P2、…、Pk

for i1 to k

do

yi Divide-and-ConquerPi               遞歸解決Pi

T MERGEy1y2,…,yk                          合并子問題

ReturnT

    其中 |P| 表示問題P的規模;n0為一閾值,表示當問題P的規模不超過n0時,問題已容易直接解出,不必再繼續分解。ADHOCP)是該分治法中的基本子算法,用于直接解小規模的問題P。因此,當P的規模不超過n0時,直接用算法ADHOCP)求解。

    算法MERGEy1y2,…,yk)是該分治法中的合并子算法,用于將P的子問題P1P2、…、Pk的相應的解y1y2、…、yk合并為P的解。

    根據分治法的分割原則,原問題應該分為多少個子問題才較適宜?各個子問題的規模應該怎樣才為適當?這些問題很難予以肯定的回答。但人們從大量實踐中發現,在用分治法設計算法時,最好使子問題的規模大致相同。換句話說,將一個問題分成大小相等的k個子問題的處理方法是行之有效的。許多問題可以取k=2。這種使子問題規模大致相等的做法是出自一種平衡子問題的思想,它幾乎總是比子問題規模不等的做法要好。

    分治法的合并步驟是算法的關鍵所在。有些問題的合并方法比較明顯,有些問題合并方法比較復雜,或者是有多種合并方案;或者是合并方案不明顯。究竟應該怎樣合并,沒有統一的模式,需要具體問題具體分析。

【問題】       大整數乘法

問題描述:

    通常,在分析一個算法的計算復雜性時,都將加法和乘法運算當作是基本運算來處理,即將執行一次加法或乘法運算所需的計算時間當作一個僅取決于計算機硬件處理速度的常數。

    這個假定僅在計算機硬件能對參加運算的整數直接表示和處理時才是合理的。然而,在某些情況下,我們要處理很大的整數,它無法在計算機硬件能直接表示的范圍內進行處理。若用浮點數來表示它,則只能近似地表示它的大小,計算結果中的有效數字也受到限制。若要精確地表示大整數并在計算結果中要求精確地得到所有位數上的數字,就必須用軟件的方法來實現大整數的算術運算。

    請設計一個有效的算法,可以進行兩個n位大整數的乘法運算。

     設XY都是n位的二進制整數,現在要計算它們的乘積XY。我們可以用小學所學的方法來設計一個計算乘積XY的算法,但是這樣做計算步驟太多,顯得效率較低。如果將每21位數的乘法或加法看作一步運算,那么這種方法要作O(n2)步運算才能求出乘積XY。下面我們用分治法來設計一個更有效的大整數乘積算法。

6-3 大整數XY的分段

    我們將n位的二進制整數XY各分為2段,每段的長為n/2位(為簡單起見,假設n2的冪),如圖6-3所示。

由此,X=A2n/2+BY=C2n/2+D。這樣,XY的乘積為:

XY=(A2n/2+B)(C2n/2+D)=AC2n+(AD+CB)2n/2+BD    1

    如果按式(1)計算XY,則我們必須進行4n/2位整數的乘法(ACADBCBD),以及3次不超過n位的整數加法(分別對應于式(1)中的加號),此外還要做2次移位(分別對應于式(1)中乘2n和乘2n/2)。所有這些加法和移位共用On)步運算。設Tn)是2n位整數相乘所需的運算總數,則由式(1),我們有:

                  2

    由此可得Tn=On2)。因此,用(1)式來計算XY的乘積并不比小學生的方法更有效。要想改進算法的計算復雜性,必須減少乘法次數。為此我們把XY寫成另一種形式:

XY=AC2n+[(A-B)(D-C)+AC+BD]2n/2+BD          3

    雖然,式(3)看起來比式(1)復雜些,但它僅需做3n/2位整數的乘法(ACBD和(A-B)(D-C)),6次加、減法和2次移位。由此可得:

                      4

    用解遞歸方程的套用公式法馬上可得其解為T(n)=O(nlog3)=O(n1.59)。利用式(3),并考慮到XY的符號對結果的影響,我們給出大整數相乘的完整算法MULT如下

function MULT(XYn); {XY2個小于2n的整數,返回結果為XY的乘積XY}

begin

S=SIGN(X)*SIGN(Y); {SXY的符號乘積}

X=ABS(X);

Y=ABS(Y); {XY分別取絕對值}

if n=1 then

if (X=1)and(Y=1) then return(S)

else return(0)

else begin

A=X的左邊n/2;

B=X的右邊n/2;

C=Y的左邊n/2;

D=Y的右邊n/2;

ml=MULT(A,C,n/2);

m2=MULT(A-B,D-C,n/2);

m3=MULT(B,D,n/2);

S=S*(m1*2n+(m1+m2+m3)*2n/2+m3);

return(S);

end;

end;

    上述二進制大整數乘法同樣可應用于十進制大整數的乘法以提高乘法的效率減少乘法次數。

【問題】       最接近點對問題

問題描述:

    在應用中,常用諸如點、圓等簡單的幾何對象代表現實世界中的實體。在涉及這些幾何對象的問題中,常需要了解其鄰域中其他幾何對象的信息。例如,在空中交通控制問題中,若將飛機作為空間中移動的一個點來看待,則具有最大碰撞危險的2架飛機,就是這個空間中最接近的一對點。這類問題是計算幾何學中研究的基本問題之一。下面我們著重考慮平面上的最接近點對問題。

     最接近點對問題的提法是:給定平面上n個點,找其中的一對點,使得在n個點的所有點對中,該點對的距離最小。

    嚴格地說,最接近點對可能多于1對。為了簡單起見,這里只限于找其中的一對。

    這個問題很容易理解,似乎也不難解決。我們只要將每一點與其他n-1個點的距離算出,找出達到最小距離的兩個點即可。然而,這樣做效率太低,需要O(n2)的計算時間。我們能否找到問題的一個O (nlogn)算法。

    這個問題顯然滿足分治法的第一個和第二個適用條件,我們考慮將所給的平面上n個點的集合S分成2個子集S1S2,每個子集中約有n/2個點,然后在每個子集中遞歸地求其最接近的點對。在這里,一個關鍵的問題是如何實現分治法中的合并步驟,即由S1S2的最接近點對,如何求得原集合S中的最接近點對,因為S1S2的最接近點對未必就是S的最接近點對。如果組成S的最接近點對的2個點都在S1中或都在S2中,則問題很容易解決。但是,如果這2個點分別在S1S2中,則對于S1中任一點pS2中最多只有n/2個點與它構成最接近點對的候選者,仍需做n2/4次計算和比較才能確定S的最接近點對。因此,依此思路,合并步驟耗時為O(n2)。整個算法所需計算時間T(n)應滿足:

T(n)=2T(n/2)+O(n2)

    它的解為T(n)=O(n2),即與合并步驟的耗時同階,顯示不出比用窮舉的方法好。從解遞歸方程的套用公式法,我們看到問題出在合并步驟耗時太多。這啟發我們把注意力放在合并步驟上。

    為了使問題易于理解和分析,我們先來考慮一維的情形。此時S中的n個點退化為x軸上的n個實數x1x2、…、xn。最接近點對即為這n個實數中相差最小的2個實數。我們顯然可以先將x1x2、…、xn排好序,然后,用一次線性掃描就可以找出最接近點對。這種方法主要計算時間花在排序上,因此如在排序算法中所證明的,耗時為O(nlogn)。然而這種方法無法直接推廣到二維的情形。因此,對這種一維的簡單情形,我們還是嘗試用分治法來求解,并希望能推廣到二維的情形。

    假設我們用x軸上某個點mS劃分為2個子集S1S2,使得S1={xS | xm}S2={xS | x>m}。這樣一來,對于所有pS1qS2p<q

    遞歸地在S1S2上找出其最接近點對{p1p2}{q1q2},并設δ=min{|p1-p2||q1-q2|}S中的最接近點對或者是{p1p2},或者是{q1q2},或者是某個{p3q3},其中p3S1q3S2。如圖1所示。

1 一維情形的分治法

    我們注意到,如果S的最接近點對是{p3q3},即 | p3-q3 | < δ,則p3q3兩者與m的距離不超過δ,即 | p3-m | < δ| q3-m | < δ,也就是說,p3(m-δm)q3(mm+δ)。由于在S1中,每個長度為δ的半閉區間至多包含一個點(否則必有兩點距離小于δ),并且mS1S2的分割點,因此(m-δm)中至多包含S中的一個點。同理,(mm+δ)中也至多包含S中的一個點。由圖1可以看出,如果(m-δm)中有S中的點,則此點就是S1中最大點。同理,如果(mm+δ)中有S中的點,則此點就是S2中最小點。因此,我們用線性時間就能找到區間(m-δm)(mm+δ)中所有點,即p3q3。從而我們用線性時間就可以將S1的解和S2的解合并成為S的解。也就是說,按這種分治策略,合并步可在O(n)時間內完成。這樣是否就可以得到一個有效的算法了呢?

    還有一個問題需要認真考慮,即分割點m的選取,及S1S2的劃分。選取分割點m的一個基本要求是由此導出集合S的一個線性分割,即S=S1S2 S1S2=Φ,且S1 {x | xm}S2 {x | x>m}。容易看出,如果選取m=[maxS+minS]/2,可以滿足線性分割的要求。選取分割點后,再用O(n)時間即可將S劃分成S1={xS | xm}S2={xS | x>m}。然而,這樣選取分割點m,有可能造成劃分出的子集S1S2的不平衡。例如在最壞情況下,|S1|=1|S2|=n-1,由此產生的分治法在最壞情況下所需的計算時間Tn應滿足遞歸方程:

Tn=Tn-1+On

    它的解是Tn=On2。這種效率降低的現象可以通過分治法中“平衡子問題”的方法加以解決。也就是說,我們可以通過適當選擇分割點m,使S1S2中有大致相等個數的點。自然地,我們會想到用Sn個點的坐標的中位數來作分割點。在選擇算法中介紹的選取中位數的線性時間算法使我們可以在On時間內確定一個平衡的分割點m

    至此,我們可以設計出一個求一維點集S中最接近點對的距離的算法pair如下。

Float pairS;

{     if | S | =2   δ= | x[2]x[1] |           /*x[1..n]存放的是Sn個點的坐標*/

else  

{     if ( | S | =1)   δ=

           else

{     m=S中各點的坐標值的中位數;

               構造S1S2,使S1={xS | xm}S2={xS | xm};

δ1=pair(S1);

                δ2=pair(S2);

            p=max(S1);

            q=min(S2);

            δ=min(δ1δ2q-p);

}

return(δ);

}

  

上一頁  [1] [2] [3] [4] [5] [6] 下一頁

轉帖于:計算機等級考試_考試吧
文章搜索  
看了本文的網友還看了:
計算機等級考試權威輔導教材: 訂書電話:010-62168566  更多>>>
網友評論
昵 稱: *  評 分: 1分 2分 3分 4分 5分
標題:   匿名發表    (共有條評論)查看全部評論>>
版權聲明 -------------------------------------------------------------------------------------
  如果計算機等級考試網所轉載內容不慎侵犯了您的權益,請與我們聯系,我們將會及時處理。如轉載本計算機等級考試網內容,請注明出處。
關于本站  網站聲明  廣告服務  聯系方式  付款方式  站內導航  客服中心  友情鏈接  考試論壇  網站地圖
Copyright © 2004-2008 考試吧計算機等級考試網 All Rights Reserved    
中國科學院研究生院權威支持(北京) 電 話:010-62168566 傳 真:010-62192699
百度大聯盟黃金認證  十佳網絡教育機構  經營許可證號:京ICP060677
主站蜘蛛池模板: 免费人成视网站在线不卡 | 国产人免费人成免费视频 | 久久精品视频16 | 色香蕉在线视频 | 欧美日韩在线免费 | 日日操综合 | 亚洲v天堂 | 黄色成人在线视频 | 男女性接交无遮挡免费看视频 | 综合国产在线 | 天天色天天插 | 欧美视频精品在线观看 | 国产成人精品无缓存在线播放 | 成人短视频视频在线观看网站 | 一级特黄a免费大片 | 国产成人ae在线观看网站站 | 偷偷要色偷偷 | 九九视频在线看精品 | 欧美成人午夜影院 | 韩国久播影院理论片不卡影院 | 国产精品日本欧美一区二区 | 午夜宅男影院 | 日韩中文字幕一在线 | 欧美国产三级 | 欧美日韩三级在线观看 | 久久久7777888精品 | 国产精品一区二区三区免费视频 | 亚洲一区无码中文字幕 | 欧美videosde极品另类 | 国产精品欧美日韩视频一区 | 亚洲网址 | 高清色视频| 欧美成人专区 | a级精品九九九大片免费看 a级精品国产片在线观看 | 免费看的黄色大片 | 欧美成狂野欧美在线观看 | 亚洲视频在线免费播放 | 免费黄色小视频网站 | 色狠狠狠狠综合影视 | 国产一级αv片免费观看 | 色午夜视频 |