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

網站首頁
分類導航
試題中心
下載中心
英語學習
繽紛校園
考試論壇
網站留言
客服中心
 常用算法設計方法
【字體:
常用算法設計方法
http://www.top-99.com.cn 來源:老頑童 點擊: 更新:2005-4-20

【問題】       n皇后問題

    問題描述:求出在一個n×n的棋盤上,放置n個不能互相捕捉的國際象棋“皇后”的所有布局。

       這是來源于國際象棋的一個問題;屎罂梢匝刂v橫和兩條斜線4個方向相互捕捉。如圖所示,一個皇后放在棋盤的第4行第3列位置上,則棋盤上凡打“×”的位置上的皇后就能與這個皇后相互捕捉。

      

1

2

3

4

5

6

7

8

 

 

×

 

 

×

 

 

×

 

×

 

×

 

 

 

 

×

×

×

 

 

 

 

×

×

Q

×

×

×

×

×

 

×

×

×

 

 

 

 

×

 

×

 

×

 

 

 

 

 

×

 

 

×

 

 

 

 

×

 

 

 

×

 

    從圖中可以得到以下啟示:一個合適的解應是在每列、每行上只有一個皇后,且一條斜線上也只有一個皇后。

       求解過程從空配置開始。在第1列至第m列為合理配置的基礎上,再配置第m+1列,直至第n列配置也是合理時,就找到了一個解。接著改變第n列配置,希望獲得下一個解。另外,在任一列上,可能有n種配置。開始時配置在第1行,以后改變時,順次選擇第2行、第3行、…、直到第n行。當第n行配置也找不到一個合理的配置時,就要回溯,去改變前一列的配置。得到求解皇后問題的算法如下:

       {     輸入棋盤大小值n

              m=0;

              good=1;

              do {

                     if (good)

                            if (m==n)

                            {     輸出解;

                                   改變之,形成下一個候選解;

                            }

                            else  擴展當前候選接至下一列;

                     else  改變之,形成下一個候選解;

                     good=檢查當前候選解的合理性;

              } while (m!=0);

       }

       在編寫程序之前,先確定邊式棋盤的數據結構。比較直觀的方法是采用一個二維數組,但仔細觀察就會發現,這種表示方法給調整候選解及檢查其合理性帶來困難。更好的方法乃是盡可能直接表示那些常用的信息。對于本題來說,“常用信息”并不是皇后的具體位置,而是“一個皇后是否已經在某行和某條斜線合理地安置好了”。因在某一列上恰好放一個皇后,引入一個一維數組(col[ ]),值col[i]表示在棋盤第i列、col[i]行有一個皇后。例如:col[3]=4,就表示在棋盤的第3列、第4行上有一個皇后。另外,為了使程序在找完了全部解后回溯到最初位置,設定col[0]的初值為0當回溯到第0列時,說明程序已求得全部解,結束程序運行。

       為使程序在檢查皇后配置的合理性方面簡易方便,引入以下三個工作數組:

(1)       數組a[ ]a[k]表示第k行上還沒有皇后;

(2)       數組b[ ],b[k]表示第k列右高左低斜線上沒有皇后;

(3)       數組 c[ ],c[k]表示第k列左高右低斜線上沒有皇后;

    棋盤中同一右高左低斜線上的方格,他們的行號與列號之和相同;同一左高右低斜線上的方格,他們的行號與列號之差均相同。

       初始時,所有行和斜線上均沒有皇后,從第1列的第1行配置第一個皇后開始,在第mcol[m]行放置了一個合理的皇后后,準備考察第m+1列時,在數組a[ ]、b[ ]c[ ]中為第m列,col[m]行的位置設定有皇后標志;當從第m列回溯到第m-1列,并準備調整第m-1列的皇后配置時,清除在數組a[ ]、b[ ]c[ ]中設置的關于第m-1列,col[m-1]行有皇后的標志。一個皇后在m列,col[m]行方格內配置是合理的,由數組a[ ]b[ ]c[ ]對應位置的值都為1來確定。細節見以下程序:

【程序】

# include <stdio.h>

# include <stdlib.h>

# define   MAXN    20

int n,m,good;

int col[MAXN+1],a[MAXN+1],b[2*MAXN+1],c[2*MAXN+1];

 

void main()

{     int j;

       char awn;

       printf(“Enter n:    “);   scanf(“%d”,&n);

       for (j=0;j<=n;j++)   a[j]=1;

       for (j=0;j<=2*n;j++)      cb[j]=c[j]=1;

       m=1;       col[1]=1;        good=1;  col[0]=0;

       do {

              if (good)

                     if (m==n)

                     {     printf(“\t”);

                            for (j=1;j<=n;j++)

                                   printf(“%3d\t%d\n”,j,col[j]);

                            printf(“Enter  a  character (Q/q  for  exit)!\n”);

                            scanf(“%c”,&awn);

                            if (awn==’Q’||awn==’q’)      exit(0);

                            while (col[m]==n)

                            {     m--;

                                   a[col[m]]=b[m+col[m]]=c[n+m-col[m]]=1;

                            }

                            col[m]++;

                     }

                     else

                     {     a[col[m]]=b[m+col[m]]=c[n+m-col[m]]=0;

                            col[++m]=1;

                     }

              else

              {     while (col[m]==n)

                     {     m--;

                            a[col[m]]=b[m+col[m]]=c[n+m-col[m]]=1;

                     }

                     col[m]++;

              }

              good=a[col[m]]&&b[m+col[m]]&&c[n+m-col[m]];

       } while (m!=0);

}

       試探法找解算法也常常被編寫成遞歸函數,下面兩程序中的函數queen_all()和函數queen_one()能分別用來解皇后問題的全部解和一個解。

【程序】

# include <stdio.h>

# include <stdlib.h>

# define   MAXN    20

int n;

int col[MAXN+1],a[MAXN+1],b[2*MAXN+1],c[2*MAXN+1];

void main()

{     int j;

       printf(“Enter n:    “);   scanf(“%d”,&n);

       for (j=0;j<=n;j++)   a[j]=1;

       for (j=0;j<=2*n;j++)      cb[j]=c[j]=1;

       queen_all(1,n);

}

 

void queen_all(int k,int n)

{     int i,j;

       char awn;

       for (i=1;i<=n;i++)

              if (a[i]&&b[k+i]&&c[n+k-i])

              {     col[k]=i;

                     a[i]=b[k+i]=c[n+k-i]=0;

                     if (k==n)

                     {     printf(“\t”);

                            for (j=1;j<=n;j++)

                                   printf(“%3d\t%d\n”,j,col[j]);

                            printf(“Enter  a  character (Q/q  for  exit)!\n”);

                            scanf(“%c”,&awn);

                            if (awn==’Q’||awn==’q’)      exit(0);

                     }

                     queen_all(k+1,n);

                     a[i]=b[k+i]=c[n+k-i];

              }

}

       采用遞歸方法找一個解與找全部解稍有不同,在找一個解的算法中,遞歸算法要對當前候選解最終是否能成為解要有回答。當它成為最終解時,遞歸函數就不再遞歸試探,立即返回;若不能成為解,就得繼續試探。設函數queen_one()返回1表示找到解,返回0表示當前候選解不能成為解。細節見以下函數。

【程序】

# define   MAXN    20

       int n;

       int col[MAXN+1],a[MAXN+1],b[2*MAXN+1],c[2*MAXN+1];

       int queen_one(int k,int n)

       {     int i,found;

              i=found=0;

              While (!found&&i<n)

              {     i++;

                     if (a[i]&&b[k+i]&&c[n+k-i])

                     {     col[k]=i;

                            a[i]=b[k+i]=c[n+k-i]=0;

                            if (k==n) return 1;

                            else

                                   found=queen_one(k+1,n);

                            a[i]=b[k+i]=c[n+k-i]=1;

                     }

              }

              return found;

       }

六、貪婪法

       貪婪法是一種不追求最優解,只希望得到較為滿意解的方法。貪婪法一般可以快速得到滿意的解,因為它省去了為找最優解要窮盡所有可能而必須耗費的大量時間。貪婪法常以當前情況為基礎作最優選擇,而不考慮各種可能的整體情況,所以貪婪法不要回溯。

       例如平時購物找錢時,為使找回的零錢的硬幣數最少,不考慮找零錢的所有各種發表方案,而是從最大面值的幣種開始,按遞減的順序考慮各幣種,先盡量用大面值的幣種,當不足大面值幣種的金額時才去考慮下一種較小面值的幣種。這就是在使用貪婪法。這種方法在這里總是最優,是因為銀行對其發行的硬幣種類和硬幣面值的巧妙安排。如只有面值分別為1511單位的硬幣,而希望找回總額為15單位的硬幣。按貪婪算法,應找111單位面值的硬幣和41單位面值的硬幣,共找回5個硬幣。但最優的解應是35單位面值的硬幣。

【問題】       裝箱問題

    問題描述:裝箱問題可簡述如下:設有編號為0、1、…、n-1n種物品,體積分別為v0、v1、…、vn-1。將這n種物品裝到容量都為V的若干箱子里。約定這n種物品的體積均不超過V,即對于0in,有0viV。不同的裝箱方案所需要的箱子數目可能不同。裝箱問題要求使裝盡這n種物品的箱子數要少。

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

{     輸入箱子的容積;

       輸入物品種數n;

       按體積從大到小順序,輸入各物品的體積;

       預置已用箱子鏈為空;

       預置已用箱子計數器box_count0

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

       {     從已用的第一只箱子開始順序尋找能放入物品i 的箱子j

              if (已用箱子都不能再放物品i

              {     另用一個箱子,并將物品i放入該箱子;

                     box_count++;

              }

              else

                     將物品i放入箱子j

       }

}

       上述算法能求出需要的箱子數box_count,并能求出各箱子所裝物品。下面的例子說明該算法不一定能找到最優解,設有6種物品,它們的體積分別為:6045、35202020單位體積,箱子的容積為100個單位體積。按上述算法計算,需三只箱子,各箱子所裝物品分別為:第一只箱子裝物品1、3;第二只箱子裝物品2、45;第三只箱子裝物品6。而最優解為兩只箱子,分別裝物品1、452、3、6。

       若每只箱子所裝物品用鏈表來表示,鏈表首結點指針存于一個結構中,結構記錄尚剩余的空間量和該箱子所裝物品鏈表的首指針。另將全部箱子的信息也構成鏈表。以下是按以上算法編寫的程序。

【程序】

# include <stdio.h>

# include <stdlib.h>

typedef  struct  ele

{     int  vno;

       struct  ele  *link;

}     ELE;

typedef  struct  hnode

{     int  remainder;

       ELE  *head;

       Struct  hnode  *next;

}     HNODE;

 

void  main()

{     int  n, i, box_count, box_volume, *a;

       HNODE  *box_h,  *box_t,  *j;

       ELE   *p,  *q;

       Printf(“輸入箱子容積\n”);

       Scanf(“%d”,&box_volume);

       Printf(“輸入物品種數\n”);

       Scanf(“%d”,&n);

       A=(int *)malloc(sizeof(int)*n);

       Printf(“請按體積從大到小順序輸入各物品的體積:”);

       For (i=0;i<n;i++)    scanf(“%d”,a+i);

       Box_h=box_t=NULL;

       Box_count=0;

       For (i=0;i<n;i++)

       {     p=(ELE *)malloc(sizeof(ELE));

              p->vno=i;

              for (j=box_h;j!=NULL;j=j->next)

                     if (j->remainder>=a[i])   break;

              if (j==NULL)

              {     j=(HNODE *)malloc(sizeof(HNODE));

                     j->remainder=box_volume-a[i];

                     j->head=NULL;

                     if (box_h==NULL)        box_h=box_t=j;

                     else  box_t=boix_t->next=j;

                     j->next=NULL;

                     box_count++;

              }

              else  j->remainder-=a[i];

              for (q=j->next;q!=NULL&&q->link!=NULL;q=q->link);

              if (q==NULL)

              {     p->link=j->head;

                     j->head=p;

              }

              else

              {     p->link=NULL;

                     q->link=p;

              }

       }

       printf(“共使用了%d只箱子,box_count);

       printf(“各箱子裝物品情況如下:”);

       for (j=box_h,i=1;j!=NULL;j=j->next,i++)

       {     printf(“%2d只箱子,還剩余容積%4d,所裝物品有;\n”,I,j->remainder);

              for (p=j->head;p!=NULL;p=p->link)

                     printf(“%4d”,p->vno+1);

              printf(“\n”);

       }

}

 

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

文章錄入:xihuyu2000    責任編輯:xihuyu2000  
 版權聲明
   如果本網站所轉載內容不慎侵犯了您的權益,請與我們聯系,我們將會及時處理。如轉載本網內容,請注明出處。
 發表評論
關于本站 網站聲明 廣告服務  聯系方式  付款方式  站內導航  客服中心  友情鏈接   
Copyright © 2004-2006 考試吧 (Exam8.com) All Rights Reserved 
中國科學院研究生院中關村園區(北京市海淀區)
主站蜘蛛池模板: 人人看人人添人人谢 | 23部禽女乱小说内裤畸情 | 日本欧美在线视频 | 日本中文字幕在线观看视频 | 欧美日韩国产不卡在线观看 | 亚洲青青青网伊人精品 | 人人舔人人插 | 亚州人成网在线播放 | 日韩黄漫啪啪免费动漫 | 色视频网站大全免费 | 国产日韩免费视频 | 亚欧在线免费观看 | 肉动漫成人免费无遮羞 | 成人免费一级毛片在线播放视频 | 成人在线不卡视频 | www视频在线播放 | 日韩亚洲一区二区三区 | 日韩一区国产一级 | 怡红院视频网 | 九九久久国产精品 | 黄色在线播放网站 | 波多野结衣中文字幕2022免费 | 久久9精品 | 91香蕉视频成人 | 一级做a毛片在线看 | 激情五月激情综合网 | 欧美xx00 | 综合欧美日韩 | 亚洲精品高清国产一久久 | 日本精品区 | 日韩免费毛片全部不收费 | 看全色黄大色黄大片色责看的 | 欧美日皮| 国产特级全黄一级毛片不卡 | 两个人免费视频www 两个人看的www中文字幕 | 乱人伦视频69| 国产一级毛片夜一级毛片 | 中国黄色一级片 | 日韩影院久久 | 高清国产精品入口麻豆 | 555夜色666夜色精品站 |