日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

backtrack回溯算法

發(fā)布時(shí)間:2023/12/3 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 backtrack回溯算法 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)自臺灣師范大學(xué)acm課程

Enumerate all n-tuples

列舉重複排列。這裡示範(fàn):列舉出「數(shù)字 1 到 10 選擇五次」全部可能的情形。
製作一個(gè)陣列,用來存放一組可能的排列(數(shù)據(jù))。

int solution[5];

例如 solution[0] = 4 表示第一個(gè)抓到的數(shù)字是 4 , solution[4] = 9 表示第五個(gè)抓到的數(shù)字是 9 。陣列中不同的格子,就是 solution vector 當(dāng)中不同的維度。

遞迴程式碼設(shè)計(jì)成這樣:

int solution[5]; // 用來存放一組可能的數(shù)據(jù)void print_solution() // 印出一組可能的數(shù)據(jù) {for (int i=0; i<5; i++)cout << i << ' ';cout << endl; }void backtrack(int n) // n 為現(xiàn)在正在列舉的維度 {// it's a solutionif (n == 5){print_solution();return;}// 逐步列舉數(shù)字1到10,並且各自遞迴下去,列舉之後的維度solution[n] = 1;backtrack(n+1);solution[n] = 2;backtrack(n+1);......solution[n] = 10;backtrack(n+1); }int main() {backtrack(0); }

輸出結(jié)果會照字典順序排列。附送一張簡圖:

注解: 其實(shí)就是利用遞歸來打印出整個(gè)字典順序。注意遞歸函數(shù)中的順序和遞歸停止條件。

Permutation

permutation 是「排列」的意思,便是數(shù)學(xué)課本中「排列組合」的排列。但是這裡並不是要計(jì)算排列有多少種,而是實(shí)際列舉出所有的排列:

現(xiàn)在有一個(gè)集合,裡面有 1 到 n 的數(shù)字,列出所有數(shù)字的排列,同樣的排列不能重複列出來。例如 {1,2,3} 所有的排列就是 {1,2,3} 、 {1,3,2} 、 {2,1,3} 、 {2,3,1} 、 {3,1,2} 、 {3,2,1} 。

permutation 的問題可以使用 backtracking 的技術(shù)來解決!

依序窮舉每個(gè)位置,針對每個(gè)位置,試著填入各種數(shù)字
一般來說, permutation 的程式碼都會長成這樣的格式:

int solution[MAX]; // 用來存放一組可能的答案 bool used[MAX]; // 紀(jì)錄數(shù)字是否使用過,用過為 truevoid permutation(int k, int n) {if (k == n) // it's a solution{for (int i=0; i<n; i++)cout << solution[i] << " ";cout << endl;}else{for (int i=0; i<n; i++) // 試著將第 k 格填入各種數(shù)字if (!used[i]){used[i] = true; // 紀(jì)錄用過的數(shù)字solution[k] = i; // 將第 k 格填入數(shù)字 kpermutation(k+1, n); // iterate next positionused[i] = false; // 回收用完的數(shù)字}} }int main() {for (int i=0; i < MAX; i++) // initializationused[i] = false;permutation(0, 10); // 印出0~9,一共10個(gè)數(shù)字的所有排列 }

permutation 的問題都可以使用這段程式碼來解決。而且這支程式,是以字典順序來列舉出所有排列。所以它真的很有用,不妨參考看看。

依序窮舉每個(gè)數(shù)字,針對每個(gè)數(shù)字,試著填入各個(gè)位置
另外還有一種作法是生做這個(gè)樣子的:

int solution[MAX]; // 用來存放一組可能的答案 bool filled[MAX]; // 紀(jì)錄各個(gè)位置是否填過數(shù)字,填過為 truevoid permutation(int v, int n) {if (v == n) // it's a solution{for (int i=0; i<n; i++)cout << solution[i] << " ";cout << endl;}else{for (int i=0; i<n; i++) // 試著將數(shù)字 v 填入各個(gè)位置if (!filled[i]){filled[i] = true; // 紀(jì)錄填過的位置solution[i] = v; // 將數(shù)字 v 填入第 i 格permutation(v+1, n); // iterate next positionfilled[i] = false; // 回收位置}} }int main() {for (int i=0; i<MAX; i++) // initializationfilled[i] = false;permutation(0, 10); // 印出0~9,一共10個(gè)數(shù)字的所有排列 }

這也是一個(gè)不錯(cuò)的方法,列出來提供大家參考。多接觸各式各樣的方法,能激發(fā)一些創(chuàng)意呢!

為了講解方便,以下的文章以一開始提到的方法當(dāng)作基準(zhǔn)。

字串排列
有個(gè)常見的問題是:列出字串 abc 的所有排列,要依照字典順序列出。其實(shí)這就跟剛才介紹的東西大同小異,只要稍加修改程式碼即可。

char s[3] = {'a', 'b', 'c'}; // 字串,需要先由小到大排序過 char solution[3]; // 用來存放一組可能的答案 bool used[3]; // 紀(jì)錄該字母是否使用過,用過為 truevoid permutation(int k, int n) {if (k == n) // it's a solution{for (int i=0; i<n; i++)cout << solution[i];cout << endl;}else{// 針對solution[i]這個(gè)位置,列舉所有字母,並各自遞迴for (int i=0; i<n; i++)if (!used[i]){used[i] = true;solution[k] = s[i]; // 填入字母permutation(k+1, n);used[i] = false;}} }

總結(jié)

以上是生活随笔為你收集整理的backtrack回溯算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。