来源: 《算法竞赛进阶指南》
算法标签: 递归
题目描述
从 1~n 这 n 个整数中随机选取任意多个,输出所有可能的选择方案。
输入格式
输入一个整数n。
输出格式
每行输出一种方案。
同一行内的数必须升序排列,相邻两个数用恰好1个空格隔开。
对于没有选任何数的方案,输出空行。
本题有自定义校验器(SPJ),各行(不同方案)之间的顺序任意。
数据范围
1≤n≤15
输入样例:
3
输出样例:
3
2
2 3
1
1 3
1 2
1 2 3
思路
已知从 1~n 这 n 个整数中随机选取任意多个,输出所有可能的选择方案。
且同一行内的数必须升序排列,相邻两个数用恰好1个空格隔开。
则我们相当于在N长度的序列当中选出所有递增序列。
要做到这样的情况,我们只需要dfs暴力搜索即可,因为所选数字顺序都被自然序列1,2,3....限制,即本身就为递增。
下图为1,2,3序列 ,DFS过程演示图。
N为不选,C为选。
CPP代码
#include<iostream>
using namespace std;
const int N=20;最大值加冗余
int n,st[N];
void dfs(int x)
{
if(x>n)//x>n就表明已经走完了1到n,即序列被走完了
{
for(int i=1;i<=n;i++)
if(st[i]==1)//当前数被选择,输出当前结果
cout<<i<<" ";
cout<<endl;
return;
}
st[x]=2;//2为不选当前数字
dfs(x+1);//移动到下一个数字选择
st[x]=0;//回溯到上一层之后恢复现场
st[x]=1;//1为选择当前数字
dfs(x+1);//到下一次选择
st[x]=0;
}
int main()
{
cin>>n;
dfs(1);//从当前有一个数字选择开始跑
return 0;
}
go:
package main
import (
"fmt"
)
var vis[20] bool
var n int
func dfs(u int) {
if u==(n+1) {
for i := 1; i <= n; i++ {
if vis[i] == true {
fmt.Print(i, " ")
}
}
fmt.Print("\n")
return
}
dfs(u+1)
vis[u]=true
dfs(u+1)
vis[u]=false
}
func main() {
fmt.Scanf("%d",&n)
dfs(1)
}