生活随笔
收集整理的這篇文章主要介紹了
求全排列和组合问题
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?
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
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔為你收集整理的求全排列和组合问题的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。