推荐版本
由于输出必须要按字典序,所以可以想到,从上一个选过之后的地方开始选即可。
再加上相关的剪枝优化可以比下面两种暴力的做法的时间小很多很多。
#include<iostream>
#include<vector>
using namespace std;
int n,m;
vector<int> v;
void dfs(int u,int start){//u代表的是当前正在选第u个元素;start~n是当前可选的元素
if((n-start+u)<m){//剪枝
return ;
}
if(u==m+1){
for(int i=0;i<v.size();i++){
printf("%d ",v[i]);
}
puts("");
return;
}
for(int i=start;i<=n;i++){
v.push_back(i);
dfs(u+1,i+1);
v.pop_back();
}
}
int main(){
scanf("%d%d",&n,&m);
dfs(1,1);
return 0;
}
暴力递归版本
相比于暴力非递归版本,递归版本的就友善多了o(╥﹏╥)o~~
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int m,n;
vector<int> v;
void dfs(int u){
if(u>n){
if(v.size()==m){
for(int i=0;i<v.size();i++) printf("%d ",v[i]);
puts("");
}
return;
}
v.push_back(u);
dfs(u+1);
v.pop_back();
dfs(u+1);
}
int main(){
scanf("%d%d",&n,&m);
dfs(1);
return 0;
}
暴力非递归版
其主要的思想是,枚举1~$1^n$,在枚举这些数字的时候,其二进制表示中,每一位为1,那么该位的数字就选上,否则就不选。该思想较为简单,比较困难的是在代码的实现上。(本人太菜了o(╥﹏╥)o)。
因为对输出方案的顺序有一定的要求,因此在这个地方需要妥善的处理!我的思想是把每一种组合记录成一个字符串,
然后后序对这个字符串进行排序的处理。
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
const int N=30;
int n,m;
bool cmp(string a,string b){
int ij[N],ik[N];
for(int i=0;i<m;i++){//split a&&b,将字符串a,b按" "进行分割,并且把对应的整数形式输出到一个整数数组中
string sa=a.substr(0,a.find(" "));
sscanf(sa.c_str(),"%d",&ij[i]);
a.erase(0,a.find(" ")+1);
string sb=b.substr(0,b.find(" "));
sscanf(sb.c_str(),"%d",&ik[i]);
b.erase(0,b.find(" ")+1);
}
for(int i=0;i<m;i++){
if(ij[i]!=ik[i]) return ij[i]<ik[i];
}
return true;
}
int main(){
scanf("%d%d",&n,&m);
vector<string> ve;
int cnt=0;
int a[N];
if(m==0) puts("");
else{
for(int i=0;i<1<<n;i++){
cnt=0;
for(int j=0;j<n;j++){
if(i>>j&1){
a[cnt++]=(j+1);
if(cnt>m) continue;
}
}
if(cnt==m){//满足条件的话,就把该组条件保存在一个字符串中
string res="";
char str[N];
for(int k=0;k<m;k++){
memset(str,0,sizeof str);
sprintf(str,"%d",a[k]);//把数字转换成字符串
res=res+str+" ";
}
ve.push_back(res);
}
}
sort(ve.begin(),ve.end(),cmp);//一开始我以为可以直接按照字典序从小到大进行排序即可,但是我错了!
//因为当这里还有两位数存在,因此直接按字典序的话并不准确,因此自写了一个cmp函数用于比较排序
for(int i=0;i<ve.size();i++){
cout<<ve[i]<<endl;
}
}
return 0;
}