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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

求全排列和组合问题

發布時間:2023/12/20 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 求全排列和组合问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

1.排列:全排列n!
  使用next_permutation函數

1 輸出序列{1,2,3,4}字典序的全排列。 2 #include <iostream> 3 #include<algorithm> 4 using namespace std; 5 6 int main(int argc, char** argv) { 7 int a[4]={1,2,3,4}; 8 sort(a,a+4); 9 do{ 10 //cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<" "<<a[3]<<endl; 11 for(int i=0;i<4;i++) 12 cout<<a[i]<<" "; 13 cout<<endl; 14 }while(next_permutation(a,a+4)); 15 return 0; 16 }

輸入任意一個字符串,輸出其字典序的全排列

1 #include <iostream> 2 #include<algorithm> 3 using namespace std; 4 5 int main(int argc, char** argv) { 6 string str; 7 cin>>str; 8 sort(str.begin(),str.end()); 9 do{ 10 cout<<str<<endl; 11 }while(next_permutation(str.begin(),str.end())); 12 return 0; 13 }

遞歸法

設一組數p = {r1, r2, r3, … ,rn}, 全排列為perm(p),pn = p – {rn}。則perm(p) = r1perm(p1), r2perm(p2), r3perm(p3), … , rnperm(pn)。當n = 1時perm(p} = r1。
如:求{1, 2, 3, 4, 5}的全排列
1、首先看最后兩個數4, 5。 它們的全排列為4 5和5 4, 即以4開頭的5的全排列和以5開頭的4的全排列。
由于一個數的全排列就是其本身,從而得到以上結果。
2、再看后三個數3, 4, 5。它們的全排列為3 4 5、3 5 4、 4 3 5、 4 5 3、 5 3 4、 5 4 3 六組數。
即以3開頭的和4,5的全排列的組合、以4開頭的和3,5的全排列的組合和以5開頭的和3,4的全排列的組合.

1 #include < 2 iostream> 3 using namespace std; 4 5 void Perm(int start, int end, int a[]) { 6 //得到全排列的一種情況,輸出結果 7 if (start == end) { 8 for (int i = 0; i < end; i++) 9 cout << a[i] << ' '; 10 cout << endl; 11 return; 12 } 13 for (int i = start; i < end; i++) { 14 swap(a[start], a[i]); //交換 15 Perm(start + 1, end, a); //分解為子問題a[start+1,...,end-1]的全排列 16 swap(a[i], a[start]); //回溯 17 } 18 } 19 int main() { 20 int i, n, a[10]; 21 while (cin >> n, n) { 22 for (i = 0; i < n; i++) 23 { 24 a[i] = i + 1; 25 } 26 Perm(0, n, a); 27 } 28 return 0; 29 }

?

2.組合:C(n,k),n個數中任取k個數
遞歸法


實際上就是在n個數中,標記k個數,然后輸出這k個數的過程。使用一個visited數組來記錄相應下標的數是否被選中。

1 #include <iostream> 2 using namespace std; 3 4 void dfs(int pos, int cnt, int n, int k, int a[],bool visited[]) { 5 //已標記了k個數,輸出結果 6 if (cnt == k) { 7 for (int i = 0; i < n; i++) 8 if (visited[i]) cout << a[i] << ' '; 9 cout << endl; 10 return; 11 } 12 13 //處理到最后一個數,直接返回 14 if (pos == n) return; 15 16 //如果a[pos]沒有被選中 17 if (!visited[pos]) { 18 //選中a[pos] 19 visited[pos] = true; 20 //處理在子串a[pos+1, n-1]中取出k-1個數的子問題 21 dfs(pos + 1, cnt + 1, n, k, a,visited); 22 //回溯 23 visited[pos] = false; 24 } 25 //處理在子串a[pos+1, n-1]中取出k個數的問題 26 dfs(pos + 1, cnt, n, k, a, visited); 27 } 28 int main() { 29 int i, n, k; 30 while (cin >> n >> k, n || k) 31 { 32 int *a = new int[n]; 33 bool *visited = new bool[n]; 34 for (i = 0; i < n; i++) 35 { 36 a[i] = i + 1; 37 visited[i] = false; 38 } 39 dfs(0, 0, n, k, a, visited); 40 delete[] a; 41 delete[] visited; 42 } 43 getchar(); 44 return 0; 45 }

‘01’轉換法

本程序的思路是開一個數組,其下標表示1到n個數,數組元素的值為1表示其代表的數被選中,為0則沒選中。
首先初始化,將數組前n個元素置1,表示第一個組合為前n個數。
然后從左到右掃描數組元素值的“10”組合,找到第一個“10”組合后將其變為“01”組合,同時將其左邊的所有“1”全部移動到數組的最左端。
當第一個“1”移動到數組的n-m的位置,即n個“1”全部移動到最右端時,就得到了最后一個組合。
例如求5中選3的組合:
1 1 1 0 0 //1,2,3

1 1 0 1 0 //1,2,4

1 0 1 1 0 //1,3,4

0 1 1 1 0 //2,3,4

1 1 0 0 1 //1,2,5

1 0 1 0 1 //1,3,5

0 1 1 0 1 //2,3,5

1 0 0 1 1 //1,4,5

0 1 0 1 1 //2,4,5

0 0 1 1 1 //3,4,5

1 #include <iostream> 2 using namespace std; 3 4 //輸出結果 5 void printRes(int* a, bool* index, int n) 6 { 7 for (int i=0;i<n;i++) 8 { 9 if (index[i]) 10 { 11 cout << a[i] << " "; 12 } 13 } 14 cout << endl; 15 } 16 17 //檢查最后k個位置是否已全變成0 18 bool hasDone(bool* index, int n, int k) 19 { 20 for (int i=n-1;i>=n-k;i--) 21 { 22 if (!index[i]) 23 { 24 return false; 25 } 26 } 27 return true; 28 } 29 30 void Comb(int* a, int n, int k) 31 { 32 bool *index = new bool[n](); 33 //選中前k個位置 34 for (int i = 0; i < k; i++) 35 { 36 index[i] = true; 37 } 38 printRes(a, index, n); 39 40 while (!hasDone(index, n, k)) 41 { 42 //從左到右掃描數組 43 for (int i = 0; i < n - 1; i++) 44 { 45 //找到第一個“10”組合將其變成"01"組合 46 if (index[i] && !index[i + 1]) 47 { 48 index[i] = false; 49 index[i + 1] = true; 50 51 //將"01"組合左邊的1移到最左邊 52 int count = 0; 53 for (int j = 0; j < i; j++) 54 { 55 if (index[j]) 56 { 57 index[j] = false; 58 index[count++] = true; 59 } 60 } 61 printRes(a, index, n); 62 break; 63 } 64 } 65 } 66 delete[] index; 67 } 68 int main() 69 { 70 int n,k; 71 while (cin>>n>>k) 72 { 73 int *a = new int[n](); 74 for (int i = 0; i < n; i++) 75 { 76 a[i] = i+1; 77 } 78 Comb(a, n, k); 79 delete[] a; 80 } 81 82 return 0; 83 }

?

轉載于:https://www.cnblogs.com/zzw1024/p/10537968.html

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的求全排列和组合问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。