回溯法(揹包問題和八皇后問題)

2021-06-19 13:19:14 字數 3702 閱讀 5937

演算法分析

給定n

中物品和乙個容量為

c的揹包,物品

i的重量為

wi,其價值為

vi,揹包問題是如何選擇裝入揹包的物品(物品不可分割),使得裝入揹包的物品的價值為最大

,考慮到每種物品只有2 

種選擇,即裝入揹包或不裝入揹包,並且物品數和揹包容量已給定,要計算裝入揹包物品的最大價值和最優裝入方案,可用回溯法搜尋子集樹的演算法進行求解

物品有n

種,揹包容量為

c,分別用

p[i]

和w[i]

儲存第i

種物品的價值和重量,用

x[i]標記第

i種物品是否裝入揹包,用

bestx[i]

儲存第i

種物品的最優裝載方案;

二. 用遞迴函式

backtrack (i,cp,cw)

來實現回溯法搜尋子集樹(形式引數

i表示遞迴深

度,n用來控制遞迴深度,形式引數cp和

cw表示當前總價值和總重量,

bestp

表示當前

最優總價值):

① 若i >n

,則演算法搜尋到乙個葉結點,判斷當前總價值是否最優:

1> 若

cp>bestp

,更新當前最優總價值為當前總價值(即

bestp=cp

),更新

裝載方案(即bestx[i]=x[i]( 1≤i

≤n));② 採用for

迴圈對物品

i裝與不裝兩種情況進行討論(0≤

j≤1):

1> x[i]=j;

2> 若總重量不大於揹包容量(即

cw+x[i]*w[i]<=c

),則更新當前總價 

br=""> 

值和總重量(即

cw+=w[i]*x[i],cp+=p[i]*x[i]), 

對物品i+1

呼叫遞迴函

數backtrack(i+1,cp,cw) 

繼續進行裝載;

3> 函式

backtrack(i+1,cp,cw)

呼叫結束後則返回當前總價值和總重量

(即 cw-=w[i]*x[i],cp-=p[i]*x[i]

);4> 當

j>1

時,for

迴圈結束;

③ 當i=1

時,若已測試完所有裝載方案,外層呼叫就全部結束;

三主函式呼叫一次backtrack(1,0,0)

即可完成整個回溯搜尋過程,最終得到的

bestp

和bestx[i]

即為所求最大總價值和最優裝載方案。 

.#include

int n,c,bestp;//物品的個數,揹包的容量,最大價值

int p[10000],w[10000],x[10000],bestx[10000];//物品的價值,物品的重量,

x[i]

暫存物品的選中情況

,物品的選中情況

void backtrack(int i,int cp,int cw)

} else 

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

} }

int main()

結果 1.

..輸入皇后個數:1 

1 2...請輸入揹包最大容量:15

請輸入物品個數:3

請依次輸入物品的重量:

5 6 4

請依次輸入物品的價值:

7 5 9

最大價值為:21

被選中的物品依次是(0

表示未選中,

1表示選中

1 1 1

小結:回溯法是個好東西, 當自己對乙個問題沒有任何思路的時候就可以用回溯法, 雖然效率是乙個嚴重的問題, 但是卻能給問題乙個形象的解釋, 或者可以從回溯法想到乙個不錯的演算法也不一定

當遇到乙個可以用到回溯法的時候需要按照如下步驟進行:

1. 確定問題的乙個解空間樹, 這個解空間樹至少包含乙個你需要的那個解, 否則這個樹就完全沒有意義了

2. 組織好這棵樹, 弄明白這棵樹的每乙個節點代表什麼, 每乙個分支代表什麼

3. 從這棵樹的根節點不斷的向下深搜, 當遇到不合適的節點的時候直接跳過以這個節點為根的子樹

4. 當搜尋到了葉子節點的時候就回溯

分析

1...

八皇后問題

是十九世紀著名數學家高斯於1850

年提出的。

問題是:在8*8

的棋盤上擺放

8個皇后,使其不能互相攻擊,即任意的兩個皇后不能處在同意行,同一列,或同意斜線上。可以把八皇后問題拓展為

n皇后問題,即在

n*n的棋盤上擺放

n個皇后,使其任意兩個皇后都不能處於同一行、同一列或同一斜線上。

...每一行可以而且必須放乙個皇后,所以n

皇后問題的解可以用乙個

n元向量x=(

x1,x2

,.....x

n)表示,其中,1≤i

≤n且1≤

xi≤n,即第

n個皇后放在第i行第

xi列上。由於兩個皇后不能放在同一列上,所以,解向量x

必須滿足的約束條件為:xi

≠xj;若兩個皇后的擺放位置分別是(

i,xi

)和(j,x

j),在棋盤上斜率為-1

的斜線上,滿足條件

i-j=xi-x

j;在棋盤上斜率為

1的斜線上,滿足條件

i+j=xi+x

j;綜合兩種情況,由於兩個皇后不能位於同一斜線上,所以,解向量

x必須滿足的約束條件為

:|i-xi|

≠|j-xj|

1...#include

#include

int x[100];

bool place(int k)//考察皇后

k放置在

x[k]

列是否發生衝突

void queue(int n)

else if(x[k]<=n&&k

k=k+1;//放置下乙個皇后

else

}

}

void main()

..

八皇后問題(回溯法)

問題描述 八皇后問題是十九世紀著名數學家高斯於1850年提出的。問題是 在8 8的棋盤上擺放8個皇后,使其不能互相攻擊,即任意的兩個皇后不能處在同意行,同一列,或同意斜線上。可以把八皇后問題拓展為n皇后問題,即在n n的棋盤上擺放n個皇后,使其任意兩個皇后都不能處於同一行 同一列或同一斜線上。問題分...

回溯法 八皇后問題

八皇后問題是高斯於1850年提出的,這是乙個典型的回溯演算法的問題。八皇后問題的大意如下 西洋棋的棋盤有8 行 8 列共64個單元格,在棋盤上擺放八個皇后,使其不能互相攻擊,也就 是說任意兩個皇后都不能處於同一行 同一列或同一斜線上。問總共有多少種擺放方法,每一種擺 放方式是怎樣的。首先來分析八皇后...

八皇后問題 回溯法

在8 8格的西洋棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行 同一列或同一斜線上,問有多少種擺法 就拿四皇后來說吧 我們首先需要建立乙個一維陣列 這個陣列裡存放的就是皇后在該列合適的位置 這個陣列存放的是皇后放的行數,我們首先在第一列中找乙個可以放的地方,很明顯第乙個位置就可以...