从 1~n 这 n 个整数中随机选取任意多个,输出所有可能的选择方案。
输入格式
输入一个整数n。
输出格式
每行输出一种方案。
同一行内的数必须升序排列,相邻两个数用恰好1个空格隔开。
对于没有选任何数的方案,输出空行。
本题有自定义校验器(SPJ),各行(不同方案)之间的顺序任意。
数据范围
1≤n≤15
输入样例:
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;
}
浙公网安备 33010602011771号