生活随笔
收集整理的這篇文章主要介紹了
排列组合(两种方法)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
排列組合是組合數學的基礎,從n個不同元素中任取m個,約定1<m≤n,按任意一種次序排成一列,稱為排列,其排列種數記為(Arrange)A(n,m)。從n個不同元素中任取m個(約定1<m<n)成一組,稱為一個組合,其組合種數記為C(n,m)。計算A(n,m)與C(n,m)只要簡單進行乘運算即可,要具體展現出排列的每一列與組合的每一組,決非輕而易舉。
注意:
1、 排列A有序 A(n,m) = n * (n-1) * …*(n-m+1)
2、 組合C無序 C(n,m) = A(n,m) / A(m,m)
3、 注意到組合與組成元素的順序無關,約定組合中的組成元素按遞增排序。因而,把以上程序中的約束條件作簡單修改: a[i]==a[j] 修改為 a[i]>=a[j]
有兩種方法:
1、DFS方法適用于不重復的情況下,分治法可適用于有元素相同的情況下
2:分治法元素相同時的情況為:
//1、arr[i]!=arr[k],因為這樣交換后剩下的元素是一樣的,兩種全排列是重復的
//2、arr[k+1]—>arr[i-1],也就是k和i之間的元素不能和arr[i]相等,因為k和i之間的元素都是和k交換過的,
//如果arr[i]和arr[k+1]—>arr[i-1]之間的元素有相等的,那么這兩種排列也是重復的
//下面代碼中||運算前的是第一種情況,或運算之后的是第二種情況
排列:DFS
方法一:回溯法(全排列的數組中不可以有重復的元素)
#include <iostream>
#include <vector>using namespace std;
int count =
0;
vector<int> v;
bool Single(
int num)
{
for (
int i=
0; i<v.size(); ++i){
if (v[i] == num)
return false; }
return true;
}
void perm(
int n,
int m)
{
if (m ==
0){++count;
return;}
for (
int i=
1; i<=n; ++i) {
if (Single(i)){v.push_back(i);perm(n, m-
1);v.pop_back(); }}
}
int main()
{
int n, m;
cin >> n >> m;perm(n, m);
cout << count << endl;
return 0;
}
回溯法:組合(組合的數組中不可以有重復的元素)
#include <iostream>
#include <vector>using namespace std;
int count =
0;
vector<int> v;
bool Single(
int num)
{
for (
int i=
0; i<v.size(); ++i){
if (v[i] == num)
return false; }
return true;
}
void perm(
int n,
int m)
{
if (m ==
0){++count;
return;}
for (
int i=
1; i<=n; ++i) {
if (Single(i)){v.push_back(i);perm(n, m-
1);v.pop_back(); }}
}
int main()
{
int n, m;
cin >> n >> m;perm(n, m);
cout << count << endl;
return 0;
}
全排列方法二:分治法(數組中可以有重復元素,下一個程序就是怎樣消除重復)
#include <iostream>using namespace std;
int count =
0;
void swap(
int* arr,
int i,
int j)
{arr[i] = arr[i] ^ arr[j];arr[j] = arr[i] ^ arr[j]; arr[i] = arr[i] ^ arr[j];
}
void perm(
int* arr,
int len,
int m,
int n)
{
if (m == n){++count;
return; }
for (
int i=m; i<=n; ++i){swap(arr, m, i);perm(arr, len, m+
1, n); swap(arr, m, i); }
}
int main()
{
int arr[
9];
for (
int i=
0; i<
9; ++i){arr[i] = i+
1; }perm(arr,
9,
0,
8);
cout << count << endl;
return 0;
}
分治法:全排列(數組中可以有重復的元素ADCD)
#include <iostream>
#include <string>using namespace std;
string
str;
string* pwd;
int n;
int count =
0;
void swap(
int index,
int i,
int j)
{
char tmp = pwd[
index][i];pwd[
index][i] = pwd[
index][j];pwd[
index][j] = tmp;
}
bool Appear(
int index,
char target,
int begin,
int end)
{
for (
int i=begin; i<=end; ++i){
if (target == pwd[
index][i])
return true; }
return false;
}
void perm(
int index,
int k,
int m)
{
if (k == m) {
if (
str.find(pwd[
index]) != -
1) {++
count;}
return;}
for (
int i=k; i<=m; ++i){
if ((i!=k && pwd[
index][i]==pwd[
index][k]) || Appear(
index, pwd[
index][i], k+
1, i-
1))
continue;swap(
index, k, i);perm(
index, k+
1, m);swap(
index, k, i); }
}
int main()
{cin >>
str;cin >> n;pwd =
new string[n];
for (
int i=
0; i<n; ++i)cin >> pwd[i];
for (
int i=
0; i<n; ++i){perm(i,
0,
7); }cout <<
count << endl;delete[] pwd;
return 0;
}
總結
以上是生活随笔為你收集整理的排列组合(两种方法)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。