组合型枚举
方法一:采取树状的搜索方式每一行从start到n
//组合型枚举1
#include<iostream>
using namespace std;
int n,m;
int path[10]; //路径数组,储存组合的数字
void dfs(int u,int start)
{
if(u>m)
{
for(int i=1;i<=m;i++)
{
cout<<path[i]<<" ";
}
cout<<endl;
return ;
}
for(int i=start;i<=n;i++)
{
path[u]=i;
dfs(u+1,i+1);
}
}
int main()
{
cin>>n>>m;
dfs(1,1); //从第一行第一列开始
return 0;
}
//Dawn_T
方法二:每一数字都有选和不选两种状态,依次搜索
若选,则把数存入动态数组number中继续搜索下一个,回溯后把该数删除,表示不选择该数,继续搜索下一个
当搜索到底部表示搜索完成,输出存在number中的数
//组合型枚举2
#include<iostream>
#include<vector>
using namespace std;
int n,m;
vector<int> number; //用来存选择的数字
bool pd(int x) //判断函数,判断是否搜索到底部
{
if(x>n)
return 1;
else return 0;
}
bool check(int x) //检查函数,检查是否能存入,以及是否需要继续往下搜索
{
if(number.size()>m||number.size()+n-x+1<m) //现有的数和剩下所有的数加在一起小于m
return 0; //就不可能满足条件
else return 1;
}
void dfs(int x)
{
if(!check(x)) //如果不满足,直接返回,没必要继续往下搜索
return;
if(pd(x)) //搜索到底部,输出答案
{
for(int i=0;i<number.size();i++)
{
cout<<number[i]<<" ";
}
cout<<endl;
return;
}
else
number.push_back(x); //选择该数
dfs(x+1); //搜索下一个数
number.pop_back(); //不选择该数字(恢复现场)
dfs(x+1); //搜索下一个数
}
int main()
{
cin>>n>>m;
dfs(1); //从1开始搜索
return 0;
}
//Dawn_T
排列型枚举
创建一个判断数组,储存每个数字的使用情况
//排列型枚举
#include<iostream>
using namespace std;
int n;
int path[15]; //路径数组 ,储存输出的数字
bool used[15]={false}; //判断数组,储存该数字的使用情况
bool pd(int x){ //判断函数,判断是否搜索到底部
if(x>n)
return 1;
else return 0;
}
bool check(int i){ //check函数,检查该数字是否被使用过
if(used[i])
return 1;
else return 0;
}
void dfs(int x){
if(pd(x)){ //若搜索到底部,就输出path中存放的数字
for(int i=1;i<=n;i++)
cout<<path[i]<<" ";
cout<<endl;
return; //回溯
}
for(int i=1;i<=n;i++){
if(check(i))
continue;
path[x]=i;
used[i]=true;
dfs(x+1); //下一步搜索
used[i]=false; //恢复现场
}
}
int main(){
cin>>n;
dfs(1);
return 0;
}
//Dawn_T