全排列
https://www.acwing.com/problem/content/844/
#include<iostream>
using namespace std;
const int N = 10;
int n;
int path[N];
bool st[N];
void dfs(int u){
if(u==n){
for(int i=0;i<n;i++)printf("%d ",path[i]);
puts("");
return;
}
for (int i=1;i<=n;i++)
if(!st[i]){
path[u]=i;
st[i]=true;
dfs(u+1);
st[i]=false;//不需要拔开path的,因为每次都会覆盖掉
}
}
int main(){
cin>>n;
dfs(0);
return 0;
}
全组合
递归写法
https://www.acwing.com/problem/content/description/95/
递归写法
#include<iostream>
using namespace std;
const int N=30;
int n,m;
bool st[N];
int path[N];
void comb(int u){
if(u==m){
for(int i=0;i<m;i++)printf("%d ",path[i]);
puts("");
return;
}
for(int i=1;i<=n;i++){
if(u&&i<path[u-1])continue;//古典概型的列组合方法,后面一定比前面大
if(!st[i]){
st[i]=true;
path[u]=i;
comb(u+1);
st[i]=false;
}
}
}
int main(){
cin>>n>>m;
comb(0);
return 0;
}
非递归
#include<iostream>
using namespace std;
const int N=1010;
int n,m;
int p[N];
int main(){
cin>>n>>m;
if(!n||!m)return 0;
for(int i=0;i<=m;i++)p[i]=i;
while(1){
for(int i=1;i<=m;i++)printf("%d ",p[i]);
puts("");
if(p[m]<n)++p[m];
else{
int pos=m-1;
while(p[pos]==n+pos-m)--pos;
if(!pos)break;
++p[pos++];
while(pos<=m)p[pos]=p[pos-1]+1,++pos;
}
}
return 0;
}
算组合数
long long C(int n, int m)
{
if(m < n-m) m = n-m;
long long ans = 1;
for(int i = m+1; i <= n; i++) ans *= i;
for(int i = 1; i <= n-m; i++) ans /= i;
return ans;
}
递归实现指数型枚举-取任意件的枚举方法
https://www.acwing.com/problem/content/94/
#include<iostream>
using namespace std;
int n;
void dfs(int u, int state){
if(u==n){
for(int i=0;i<n;i++)//将这个状态,的二进制数,如010,按照1不用,用2,3不用打印出来
if(state>>i&1)//看看二进制第i位是不是1,是就打印出来
cout<<i+1<<' ';//由于我们从第0位开始看的,所以要加一
cout<<endl;
return;
}
dfs(u+1, state);//不使用第u位的数字(毕竟一开始默认是0)
dfs(u+1, state|1<<u);//将第u位设置为1,表示使用第u位的数字
}
int main(){
cin>>n;
dfs(0,0);
return 0;
}
位运算的神奇规律
1.我们来看样例 5 3
结果是
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
有什么规律呢?
我们来一个1到(1<<5)-1
5 3
1–00001
2–00010
3–00011
1 2 3
4–00100
5–00101
1 2 4
6–00110
1 2 5
7–00111
8–01000
9–01001
1 3 4
10–01010
1 3 5
11–01011
12–01100
1 4 5
13–01101
14–01110
15–01111
16–10000
17–10001
2 3 4
18–10010
2 3 5
19–10011
20–10100
2 4 5
21–10101
22–10110
23–10111
24–11000
3 4 5
25–11001
26–11010
27–11011
28–11100
29–11101
30–11110
31–11111
我们可以发现0出现的位置和我们要求的数列有关!!!