1. 1〜nの順列を生成します
#include <stdio.h>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
//使用普通数组实现
void print_permutation(int n, int *A, int cur, int &cnt){ //由于无法知道数组的元素个数,用cur进行保存
if(cur == n){
cnt++;
for(int i = 0; i < n; i++)printf("%d", A[i]);
printf("\n");
}else{
for(int i = 1; i <= n; i++){
bool flag = true;
for(int j = 0; j < cur; j++){
if(A[j] == i){flag = false; break;} //不能选择里面已经有的数字
}
if(flag){
A[cur] = i;
print_permutation(n, A, cur+1, cnt); //递归调用
}
}
}
}
//使用vector容器实现
void print_permutation2(int n, vector<int>A, int &cnt){
if((int)A.size() == n){
cnt++;
for(int i = 0; i < n; i++)printf("%d", A[i]);
printf("\n");
}else{
for(int i = 1; i <= n; i++){
vector<int>::iterator iter=find(A.begin(),A.end(),i);
if(iter == A.end()){
A.push_back(i);
print_permutation2(n, A, cnt);
A.erase(A.end() - 1);
}
}
}
}
int main(){
int n = 6, A[10], cnt = 0;
vector<int>B;
printf("使用普通数组实现\n\n\n");
print_permutation(n, A, 0, cnt);
printf("\n");
printf("使用vector实现\n\n");
cnt = 0;
print_permutation2(n, B, cnt);
printf("共计%d个\n", cnt);
}
- 繰り返し可能な順列を生成する
void print_permutationR(int n, int *A, int cur, int &cnt, int *P){
if(cur == n){
cnt++;
for(int i = 0; i < n; i++)printf("%d", A[i]);
printf("\n");
}else{
for(int i = 0; i < n; i++){
int c1 = 0, c2 = 0;
for(int j = 0; j < cur; j++)if(A[j] == P[i]) c1++;
for(int j = 0; j < n; j++)if(P[i] == P[j]) if(!i || P[i] != P[i-1]) c2++;//不重复不遗漏取遍P的值
if(c1 < c2){
A[cur] = P[i];
print_permutationR(n, A, cur+1, cnt, P);
}
}
}
}
3.サブセット生成
方法1:インクリメンタル構築方法
void print_subset3(int n, int *A, int cur, int num[]){
printf("[ ");
for(int i = 0; i < cur; i++){
printf("%d ", num[A[i]]);
}
printf("]\n");
int s = cur ? A[cur-1]+1 : 0;
for(int i = s; i < n; i++){
A[cur] = i;
print_subset3(n, A, cur+1, num);
}
}
int main(){
int n = 3, A[10], P[3] = {1, 2, 3};
vector<int>B;
printf("使用增量构造法:\n");
print_subset3(n, A, 0, P);
}
方法2:ビットベクトル法を使用する
void print_subset2(int n, int *B, int cur, int num[]){
if(cur == n){
printf("[ ");
for(int i = 0; i < cur; i++){
if(B[i])printf("%d ", num[i]);
}
printf("]\n");
return ;
}
B[cur] = 1; //选择cur;
print_subset2(n, B, cur+1, num);
B[cur] = 0; //不选cur;
print_subset2(n, B, cur+1, num);
}
int main(){
int n = 3, A[10], P[3] = {1, 2, 3};
printf("使用位向量法:\n");
print_subset2(n, A, 0, P);
}
方法3、バイナリメソッドを使用し
ます。1。サブセットを記述します。バイナリビットを使用して、サブセットの特定の要素が存在するかどうかを示します。
このように、フルセットは(1 << n)-1で表すことができ、サブセットは[0、1 << n-1]の数です。
2.出力セット:バイナリANDが使用されます。(s&(1 << i))がサブセットのi番目のビットが存在することを示している場合、出力されます。
void print_subset(int n, int s, int num[]){
printf("[ ");
for(int i = 0; i < n; i++){
if(s&(1<<i))printf("%d ", num[i]);
}
printf("]\n");
}
void get_subset(int n, int num[]){
for(int i = 0; i < (1<<n); i++){
print_subset(n, i, num);
}
}
int main(){
int P[3] = {1, 1, 3};
printf("子集为:\n");
get_subset(3, P);
}
1.バックトラックの例