一.组合
:在n个数中选择m个的方案
思路
代码1
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int n,m;
vector<int>chosen;
int ans = 0;
void calc(int x) {
if( chosen.size()>m || chosen.size()+(n-x+1)<m) return ;//剪枝 选择的数字多于m个 或者已选的加剩下的数字不足m个 就不用继续选下去了
if(x==n+1){//递归到n+1层 前面没返回(即共选择了m个数 输出这m个数 并且记录答案的个数)
for(int i = 0; i < chosen.size();i++)
printf("%d ",chosen[i]);
cout << "\n" ;
ans ++;
return ;
}
calc(x+1); //下一个数不选 进入下一位
chosen.push_back(x+1);// 选下一个数
calc(x+1); // 进入下一位
chosen.pop_back();//恢复现场
return ;
}
int main(){
cin >> n >> m;
calc(1);
cout << ans ;
return 0;
}
二.排列
与顺序有关,在n个数中选择m个并按不同顺序排列的方案。
可以在代码1的基础上 ,把所求的方案×每个方案按不同顺序排列的个数。
三.关于n个数的所有子集
每个位置上的数字有选与不选两种情况,总共有2n(包括空集)情况
从 1∼n 这 n 个整数中随机选取任意多个,输出所有可能的选择方案
方法1 与代码1一样去递归从1递归到n,记录每种情况;
方法2 二进制法,二进制中每个位置的数字为0和1刚好为不选与选,若n个数便让这个二进制数为n从1开始枚举每个数字代表他的一个子集。
子集 | φ | a0 | a1 | a1, a0 | a2 | a2, a0 | a2, a1 | a2, a1, a0 |
二进制数 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 |
代码2
#include<iostream>
using namespace std;
int main(){
int n ;
cin>> n ;
for(int i = 0; i<(1<<n);i++){//从0开始枚举,每个数代表一个子集
for(int j=0;j<n;j++)//输出当前子集,每一位&1为真,及这一位为1输出j;
if(i&(1<<j)) cout << j +1<<' ';
cout << endl;
}
return 0;
}
结束语
这个是我的第一篇博客,看到的可以多提提建议。