每日一题01_递归实现指数型枚举

Posted on 2020-06-01 23:37  Nicela  阅读(155)  评论(0)    收藏  举报

从 1~n 这 n 个整数中随机选取任意多个,输出所有可能的选择方案。

输入格式

输入一个整数n。

输出格式

每行输出一种方案。

同一行内的数必须升序排列,相邻两个数用恰好1个空格隔开。

对于没有选任何数的方案,输出空行。

本题有自定义校验器(SPJ),各行(不同方案)之间的顺序任意。

数据范围

1n15

输入样例:

3

输出样例:


3
2
2 3
1
1 3
1 2
1 2 3

解法思路:

第一步:看数据范围(15):根据y总的总结,一般选择指数级别(dfs+剪枝,状态压缩dp)

第二步:读题,题型抽象:对于每个数都有两种选择,选或不选,得到抽象模型为二插树(了解深搜树的过程)

第三步:回忆二叉搜索树知识(默认采用中,左,右)

要点:当到达左叶子结点时,结束,返回上层父节点,继续访问右节点(要一直保持父节点的公平问题)

第四步:查看本题

我们需要什么:

1.一个可以装n个数的数组(最大就是15,写死就可以了)

2.记录每一位置选还是不选(开一个同样的数组,通过数字表示其状态,比如0为没选,1为选)

3.出口条件:当判断位数大于输入的n位就可以进行判断输出了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>//以上4个死记

using namespace std;
/*根据题意,先看数据范围为15,根据大佬的总结
一般选择指数级别(dfs+剪枝,状态压缩dp)
*/
const int max=16;//从1开始,位数对应
int cnt;//全局变量,默认为0
int n;//同上
int st[16];//储存每一种方案的每一位,里面为16,是因为数据范围为15
//bool vis[max];//用于储存踩过的状态,同时也用于恢复原状
void dfs(int u)//对每一位进行选或不选
{
//首先考虑边界
if(u > n)//搜索到最下层,数数此时的位数,则u为位数的下一位,在数组中数值等于位数
{
for(int m=1;m<=u;m++)//将方案输出,遍历每一位
{
if(st[m]==1)
cout<<m<<" ";
}
cout<<endl;

return;
}
/*站在中间任意节点进行操作
1.每一个点都面临选或不选的情况(两种情况并排写)
2.如果放则将该数字放入数组中,然后搜索下一步,如果不放,则直接进入下一步
3.记得将该步的状态恢复
*/

st[u]=2;//不选
dfs(u+1);
st[u]=0;//上一个函数


st[u]=1;//选
dfs(u+1);
st[u]=0;

return;
}
int main()
{

cin>>n;
dfs(1);

return 0;
}

 

博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3