n)output(x);else{for(inti=f(n,t);i<=g" />

亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

回溯法之一---算法框架及基礎

系統 2223 0

回溯法其實也是一種搜索算法,它可以方便的搜索解空間。
回溯法解題通常可以從以下三步入手:
1、針對問題,定義解空間
2、確定易于搜索的解空間結構
3、以深度優先的方式搜索解空間,并在搜索的過程中進行剪枝
回溯法通常在解空間樹上進行搜索,而解空間樹通常有子集樹和排列樹。
針對這兩個問題,算法的框架基本如下:
用回溯法搜索子集合樹的一般框架:

Cpp代碼
  1. void backtrack( int t){
  2. if (t>n)output(x);
  3. else {
  4. for ( int i=f(n,t);i<=g(n,t);i++){
  5. x[t]=h(i);
  6. if (constraint(t)&&bound(t))backtrack(t+1);
  7. }
  8. }
  9. }


用回溯法搜索排列樹的算法框架:

Cpp代碼
  1. void backtrack( int t){
  2. if (t>n)output(x);
  3. else {
  4. for ( int i=f(n,t);i<=g(n,t);i++){
  5. swap(x[t],x[i]);
  6. if (constraint(t)&&bound(t))backtrack(t+1);
  7. swap(x[t],x[i]);
  8. }
  9. }
  10. }


其中f(n,t),g(n,t)表示當前擴展結點處未搜索過的子樹的起始標號和終止標號,
h(i)表示當前擴展節點處,x[t]第i個可選值。constraint(t)和bound(t)是當前
擴展結點處的約束函數和限界函數。constraint(t)返回true時,在當前擴展結點
x[1:t]取值滿足約束條件,否則不滿足約束條件,可減去相應的子樹。bound(t)返
回的值為true時,在當前擴展結點x[1:x]處取值未使目標函數越界,還需要由backtrack(t+1)
對其相應的子樹進一步搜索。
用回溯法其實質上是提供了搜索解空間的方法,當我們能夠搜遍解空間時,
顯然我們就能夠找到最優的或者滿足條件的解。這便是可行性的問題, 而效率可以
通過剪枝函數來降低。但事實上一旦解空間的結構確定了,很大程度上時間復雜度
也就確定了,所以選擇易于搜索的解空間很重要。
下面我們看看兩個最簡單的回溯問題,他們也代表了兩種搜索類型的問題:子集合問題和
排列問題。
第一個問題:
求集合s的所有子集(不包括空集),我們可以按照第一個框架來寫代碼:

Cpp代碼
  1. #include<iostream>
  2. using namespace std;
  3. int s[3]={1,3,6};
  4. int x[3];
  5. int N=3;
  6. void print(){
  7. for ( int j=0;j<N;j++)
  8. if (x[j]==1)
  9. cout<<s[j]<< "" ;
  10. cout<<endl;
  11. }
  12. void subset( int i){
  13. if (i>=N){
  14. print();
  15. return ;
  16. }
  17. x[i]=1; //搜索右子樹
  18. subset(i+1);
  19. x[i]=0; //搜索左子樹
  20. subset(i+1);
  21. }
  22. int main(){
  23. subset(0);
  24. return 0;
  25. }



下面我們看第二個問題:排列的問題,求一個集合元素的全排列。
我們可以按照第二個框架寫出代碼:

Cpp代碼
  1. #include<iostream>
  2. using namespace std;
  3. int a[4]={1,2,3,4};
  4. const int N=4;
  5. void print(){
  6. for ( int i=0;i<N;i++)
  7. cout<<a[i]<< "" ;
  8. cout<<endl;
  9. }
  10. void swap( int *a, int i, int j){
  11. int temp;
  12. temp=a[i];
  13. a[i]=a[j];
  14. a[j]=temp;
  15. }
  16. void backtrack( int i){
  17. if (i>=N){
  18. print();
  19. }
  20. for ( int j=i;j<N;j++){
  21. swap(a,i,j);
  22. backtrack(i+1);
  23. swap(a,i,j);
  24. }
  25. }
  26. int main(){
  27. backtrack(0);
  28. return 0;
  29. }


這兩個問題很有代表性,事實上有許多問題都是從這兩個問題演變而來的。第一個問題,它窮舉了所有問題的子集,這是所有第一種類型的基礎,第二個問題,它給出了窮舉所有排列的方法,這是所有的第二種類型的問題的基礎。理解這兩個問題,是回溯算法的基礎.
下面看看一個較簡單的問題:
整數集合s和一個整數sum,求集合s的所有子集su,使得su的元素之和為sum。
這個問題很顯然是個子集合問題,我們很容易就可以把第一段代碼修改成這個問題的代碼:

Cpp代碼
  1. int sum=10;
  2. int r=0;
  3. int s[5]={1,3,6,4,2};
  4. int x[5];
  5. int N=5;
  6. void print(){
  7. for ( int j=0;j<N;j++)
  8. if (x[j]==1)
  9. cout<<s[j]<< "" ;
  10. cout<<endl;
  11. }
  12. void sumSet( int i){
  13. if (i>=N){
  14. if (sum==r)print();
  15. return ;
  16. }
  17. if (r<sum){ //搜索右子樹
  18. r+=s[i];
  19. x[i]=1;
  20. sumSet(i+1);
  21. r-=s[i];
  22. }
  23. x[i]=0; //搜索左子樹
  24. sumSet(i+1);
  25. }
  26. int main(){
  27. sumSet(0);
  28. return 0;
  29. }

回溯法之一---算法框架及基礎


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产区综合另类亚洲欧美 | 久久久网久久久久合久久久久 | 久久综合精品国产一区二区三区 | 久热re国产手机在线观看 | 99视频99 | 欧美成人精品久久精品 | 成人精品综合免费视频 | 亚洲四虎永久在线播放 | 国产亚洲精品激情都市 | 4htv影院永久免费在线地址 | 九九99香蕉在线视频美国毛片 | 亚洲成人aaa | 亚洲精品久久久久久久777 | 神马老子不卡视频在线 | 免费看成人毛片日本久久 | 欧美一级第一免费高清 | 激情5月婷婷| 日韩一区二区三区四区 | 在线看片亚洲 | 色片在线 | sese在线播放 | 性生活视频免费 | 亚洲午夜视频在线 | 波多野结衣一二三区 | 久久这里只有免费精品6www | 国产精品久久亚洲不卡动漫 | 美女视频免费在线观看 | 日韩一级视频免费观看 | 热re99久久精品国产99热 | 久久在线观看免费视频 | 91精品免费高清在线 | 国产精品久久免费 | 一区二区三区四区视频在线观看 | 天天狠狠弄夜夜狠狠躁·太爽了 | 日韩精品亚洲一级在线观看 | 欧美精品一区二区三区在线 | 精品一区二区三区影片 | 亚洲黄色在线观看视频 | 天天干天天爽 | 亚洲四虎 | 精品一区二区三区在线成人 |