回溯法的思想是:能進則進,進不了換,換不了退。
隱約束指對能否得到問題的可行解和最優解做出的約束。隱約束包括約束函式和限界函式。
關鍵步驟是:
定**空間;
確定解空間的組織結構(子集樹、排列數、m叉樹等);
搜尋解空間。
回溯法階梯的關鍵是設計有效的顯約束和隱約束。
每個物品重量w和價值v如下表所示,購物車容量為w,求不超過購物車重量的最大價值。w1
234數值
2542
w123
4數值63
54解空間=的所有子集(包括這種子集),你像這裡面就是,,,,…。顯約束為xi=0或1。
確定解空間的組織結構。由於顯約束的緣故,可以看出解空間為子集樹。
搜尋解空間
搜尋過程見問題求解。
(1)首先初始化。w=,v=,sumw=2+5+4+2=13,sumv=6+3+5+4=18,因為sumw>w,所以不能裝完,所以需要進行後續的操作。此時定義乙個cp=rp=bestp=0,x[i]=0,cw=0。
注意:在這裡w和v的下標都是從1開始。並且以左子樹為xi=1,右子樹xi=0。
(2)開始搜尋第一層(t=1)。cw=cw+w[1]=2cp=cp+v[1]=6,將2號結點加入左子樹。(2號結點是第乙個商品)
(3)拓展2號結點。考慮cw+w[2]=7左子樹。(3號結點是第2個商品)
(4)拓展3號結點。考慮cw+w[3]=11>w,所以x[3]=0,然後計算cp+rp=9+4=13>bestp(此時bestp還是0),所以將4號結點加入右子樹。(4號結點是第3個商品)
(5)拓展4號結點。考慮cw+w[4]=9左子樹。(5號結點是第4個商品)
(6)拓展5號結點。由於此時t>n,故已經找到了乙個當前的最優解,令bestp=cp(值為13),5號結點成為死結點。返回到上一結點。
(7)回溯拓展4號。此時cp=9,若將5號結點加入右子樹,cp+rp=9由於3號結點已經研究過,左子樹不可行,所以回溯到2號結點。
(8)擴充套件2號結點(t=2)。之前擴充套件了左子樹,所以現在考慮右子樹。此時cp=6,bound(t+1)=cp+rp=15>bestp,因此滿足限界條件,擴充套件右子樹,令x[2]=0,生成6號結點。(也就是第2個商品不要了)
(9)擴充套件6號結點(t=3)。cw+w[3]=6左子樹。(7號結點是第3件商品)。
(10)拓展7號結點(t=4)
cw+w[4]=8左子樹。令x[4]=1,cw=cw+w[4]=8,cp=cp+v[4]=15。(8號結點是第4件商品)
(11)拓展8號結點(t=5)。由於此時t>n,故已經找到了乙個當前的最優解,令bestp=cp(值為15),8號結點成為死結點。返回到上一結點。
(12)拓展7號結點(t=4)。考察bound(t+1)=cp+rp=11<15,成為死結點。
(13)拓展6號結點(t=3)。bound(t+1)=cp+rp=10<15,成為死結點。
(14)拓展1號結點(t=1),bound(t+1)=12<15,成為死結點。演算法結束。
double bound(int i)//計算上界
return rp+cp;
}void backtrack(int t)//t當前在第t層
bestp = cp;
return;
}if (cw + w[t] <= w)//還未到重量,可以搜尋左子樹
//若左子樹不滿足,然後看右子樹,判斷限界條件
if (bound(t + 1) > bestp)
}void initial_parameter(double w, int n)
if (sumw <= w)
backtrack(1);
cout << "放入購物車的最大價值為" << bestp << "元。" << endl;
cout << "放入購物車的物品序號為:";
for (i = 1; i <= n; i++)
cout << endl;
}
1.演算法複雜度
(1)時間複雜度:o(12n+n 2n)=o(n * 2n)。
(2)空間複雜度:o(n)。
2.演算法優化
實際上,經常我們在計算bound()函式的時候對於rp多算太多了,因為很有可能rp到某一步就超過了購物車的中梁,所以我們可以縮小上界,從而加快剪枝速度,提高搜尋效率。
上界函式bound():當前價值cp+剩餘容量可容納的剩餘物品的最大價值brp(為了能裝最大價值,所以在計算上界函式的時候可以對商品分割,但實際的時候不允許),即修改為
double bound(int i)
;bool cmp(object a1, object a2)
然後將 initial_parameter(double w, int n)的if(sumw<=w)這個語段後面加入:
sort(q,q+n,cmp);
for(i=1;i<=n;i++)
for(i=1;i<=n;i++)
然後將
for (i = 1; i <= n; i++)
修改為
for (i = 1; i <= n; i++)
部落酋長希望組織一支保衛部落的衛隊,要在居民中選出最多的居民加入,並保證衛隊中任何兩個人都不是仇敵。程式設計計算構建部落護衛隊的最佳方案。
定義問題的解空間。問題的解空間為 的所有子集(包括這種子集),你像這裡面就是,,,,…。顯約束為xi=0或1。
解空間的組織結構:子集樹,深度為n。
搜尋解空間:
bool isplace(int t)
}return status;
}//回溯法主體
void backtrack(int t)
if (isplace(t))
if (cn + n - t > bestn)//這裡可以進行優化
}
1.時間複雜度:o(n* 2n),空間複雜度為o(n)。 演算法筆記之回溯法(2)
假設地圖共有7個區域,分別是a b c d e f g,對上面順序進行編號,每個區域用乙個結點表示,相鄰的區域有連線,那麼地圖就轉化成乙個無向連線圖。定義問題的解空間。圖的m著色問題解空間形式為n元組,每個分量取值為1,2,3,m,即問題的解是乙個n元向量。由此可得,問題的解空間為,其中顯約束為xi...
演算法筆記之回溯法(2)
假設地圖共有7個區域,分別是a b c d e f g,對上面順序進行編號,每個區域用乙個結點表示,相鄰的區域有連線,那麼地圖就轉化成乙個無向連線圖。定義問題的解空間。圖的m著色問題解空間形式為n元組,每個分量取值為1,2,3,m,即問題的解是乙個n元向量。由此可得,問題的解空間為,其中顯約束為xi...
回溯 皇后 演算法筆記 演算法筆記 回溯法
1 0 1揹包問題 思路 構造乙個二叉樹,每個商品都有兩種狀態,要或者不要。如果要就在這個節點的左枝掛子節點,如果不要就在右節點掛子節點。如果全部商品都分配完狀態之後就回溯,回溯到乙個還有其他選擇的節點,接著往這個選擇發展節點,然後再回溯,然後再往下。直到無路可走,就結束了。假如限制重量是10,總共...