[推薦]數陣中的最優路徑

來源:互聯網
上載者:User

一、數值三角形中的最大路徑

   隨機產生一個n行的點數值三角形(該數值三角形的第K行有K個點,每一個點都帶有一個正整數),,即隨機產生一個7行點數值三角形。尋找從頂點開始每一步可沿左斜(L)或右斜(R)向下直至底部的一條路徑,使該路徑所經過的點的數值和最大。

 

 

 

                                        16

                                    12     13

                                  8     12     7

                               14   9       17   5

                             6    18    18     13  13

                           11  8      8      3     15    8

                          7   1   18     5      2      17   19

 

二、數值三角形中的最大路徑搜尋

   應用動態規劃,採用逆推法即從底向上逐行反推。

   隨機產生的點數值三角形的數值在二維數組a(n, n)中,同時賦給b(n, n)。 這裡數組b(i, j)為點i(i, j)到底的最大數組和,stm(i,j)是點(i,j)向左或向右的路標字元數組,實施逆推法,知b(i,j)與stm(i,j)(i=n-1,...,2,1)的值由b的第i+1行的值決定:

     若b(i+1, j+1) > b(i+1, j),則

              b(i, j)=b(i,j)+b(i+1,j+1);stm(i,j)="R"

     若b(i+1,j+1) <= b(i+1,j),則

              b(i, j)=b(i,j)+b(i+1,j);  stm(i,j)="L"

     這樣所得b(1,1)即為所示的最優路徑數值和。

    為了列印最優路徑,利用stm數組從上而下尋找:先列印a(1,1),若stm(1,1)='R',則下一個列印a(2,2),否則列印a(2,1)。一般地,對i=2,3,...,n:

     若stm(i-1, j)="R",則列印“-R”;a(i,j+1);同時賦值j++。

     若stm(i-1, j)="L",則列印"-L-";a(i,j);

     依此列印出最大路徑。

 

三、代碼實現

     // 求最優路徑程式設計(-)<br />// 利用動態規劃,求點數值三角形的最優路徑<br />#include <stdio.h><br />#include <stdlib.h><br />#include <time.h></p><p>int main(void)<br />{<br />int i, j, nRow;<br />int a[30][30], b[30][30];<br />char stm[30][30];</p><p>printf("請輸入行數Row:");<br />scanf("%d", &nRow);<br />// 初始化隨機數種子<br />srand(time(NULL));</p><p>// 輸出n行的點數值三角形<br />for (i = 1; i <= nRow; i++) {<br />for (j = 1; j <= 40 - 2 * i; j++)<br />printf(" ");<br />for (j = 1; j <= i; j++) {<br />a[i][j] = rand() % 20 + 1;<br />b[i][j] = a[i][j];<br />printf("%4d", a[i][j]);<br />}<br />putchar('/n');<br />}</p><p>// 逆推求取最大值<br />for (i = nRow - 1; i >= 1; i--)<br />for (j = 1; j <= i; j++) {<br />if (b[i + 1][j + 1] > b[i + 1][j]) {<br />b[i][j] = b[i][j] + b[i + 1][j + 1];<br />stm[i][j] = 'R';<br />}<br />else {<br />b[i][j] = b[i][j] + b[i + 1][j];<br />stm[i][j] = 'L';<br />}<br />}</p><p>printf("/n最優路徑數值和為:%d", b[1][1]);<br />printf("/n最優路徑為:%2d", a[1][1]);<br />j = 1;// 按中標引導輸出最優路徑<br />for (i = 2; i <= nRow; i++)<br />if (stm[i - 1][j] == 'R') {<br />printf("-R-%2d", a[i][j + 1]);<br />j++;<br />}<br />else<br />printf("-L-%2d", a[i][j]);</p><p>return 0;<br />}

 

 

四、數值矩陣中的最小路徑搜尋

   問題描述:隨機產生一個n行m列的整數矩陣,即隨機產生的一個7行5列的數值矩陣,在整數矩陣中尋找從左上方至右下角,每步可向下(D)或向右(R)或斜向右下(O)的一條數值和最小的路徑。

   27 28 29 18 26

   16 13 19 14 27

   32 22 39 26 21

   10 30 23 20 18

   13 11 30 29 20

   10 13 21 17 36

   34 37 15 22 36

   設計要點:應用動態規劃設計,即從右下角逐行反推左上方。確定n、m後,隨機產生的整數二維數組a(n,m)作矩陣輸出,同時賦給部分和數組b(n, m)。

   這裡數組b(i,j)為點(i,j)到右下角的最小數值和,stm(i,j)是點(i,j)向右(R)或向下(D)或向右下(O)的路標字元數組。

   注意到最後一行與最後一列各數只有一個出口,於是由b(n,m)開始向左逐個推出同行的b(n,j)(j=m-1,...,2,1);向上逐個推出同列的b(i,m)(i=n-1,...,2,1)。

   b(i,j)與stm(i,j) (i=n-1,...,2,1; j=m-1,...,2,1)的值由同一列其下面的整數b(i+1,j)與同一行其右邊的整數b(i,j+1)或其右下方的b(i+1,j+1)的值決定:

   設min=min(b(i+1,j+1),b(i,j+1),b(i+1,j);

   首先,作賦值min=b(i+1,j+1),stm(i,j)="O";

   若b(i,j+1)<min,則min=b(i,j+1),stm(i,j)="R";

   若b(i+1,j)<min,  則min=b(i+1,j),stm(i,j)="D"。

   然後賦值:b(i,j)=b(i,j)+min。

   這樣反推所得b(1,1)即為所求的最小路徑數字和。

   為了列印最小路徑,利用c數組從上而下操作:先列印a(1,1), i=1, j=1.

   ①若stm(i,j)="R",則j++,然後列印"-R-"與右邊的整數a(i,j)。

   ②若stm(i,j)="D",則i++,然後列印"-D-"與下面的整數a(i,j)。

   ③若stm(i,j)="O",則i++,j++,然後列印"-O-"與斜右下的整數a(i,j)。

   依次類推,直到列印到點a(n,m)。

  

   代碼實現:

   // 求最優路徑程式設計(-)<br />// 利用動態規劃,求數值矩陣左上方至右下角最小路徑<br />#include <stdio.h><br />#include <stdlib.h><br />#include <time.h></p><p>int main(void)<br />{<br />int m, n, row, col, min;<br />int a[30][30], b[30][30];<br />char stm[30][30];</p><p>printf("請輸入行數與列數n和m:");<br />scanf("%d%d", &n, &m);<br />// 初始化隨機數種子<br />srand(time(NULL));</p><p>// 產生並輸出n行m列的數值矩陣<br />for (row = 1; row <= n; row++) {<br />putchar('/n');<br />for (col = 1; col <= m; col++) {<br />a[row][col] = rand() % 40 + 5;// 5~44的隨機數<br />b[row][col] = a[row][col];<br />printf("%4d", a[row][col]);<br />}<br />}</p><p>// 第n行遞推為邊界條件<br />for (col = m - 1; col >= 1; col--) {<br />b[n][col] = b[n][col] + b[n][col + 1];<br />stm[n][col] = 'R';<br />}<br />// 第m列遞推為邊界條件<br />for (row = n - 1; row >= 1; row--) {<br />b[row][m] = b[row][m] + b[row + 1][m];<br />stm[row][m] = 'D';<br />}</p><p>// 逆推求取最大值b(1,1)<br />for (row = n - 1; row >= 1; row--)<br />for (col = m - 1; col >= 1; col--) {<br />min = b[row + 1][col + 1];<br />stm[row][col] = 'O';<br />if (min > b[row + 1][col]) {<br />min = b[row + 1][col];<br />stm[row][col] = 'D';<br />}<br />if (min > b[row][col + 1]) {<br />min = b[row][col + 1];<br />stm[row][col] = 'R';<br />}<br />b[row][col] = b[row][col] + min;<br />}</p><p>printf("/n最優路徑數值和為:%d", b[1][1]);<br />printf("/n最優路徑為:%2d", a[1][1]);<br />row = 1; col = 1;// 按路標引導輸出最優路徑<br />while (row < n || col < m) {<br />switch (stm[row][col]) {<br />case 'R':<br />col++;<br />printf("-R-%d", a[row][col]);<br />break;<br />case 'D':<br />row++;<br />printf("-D-%d", a[row][col]);<br />break;<br />case 'O':<br />row++;<br />col++;<br />printf("-O-%d", a[row][col]);<br />break;<br />}<br />}<br />putchar('/n');</p><p>return 0;<br />}

轉自《趣味C程式設計集錦》

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.