题目描述
从 1~n 这 n 个整数中随机选出 m 个,输出所有可能的选择方案。
输入格式
两个整数 n,m ,在同一行用空格隔开。
输出格式
按照从小到大的顺序输出所有方案,每行1个。
首先,同一行内的数升序排列,相邻两个数用一个空格隔开。
其次,对于两个不同的行,对应下标的数一一比较,字典序较小的排在前面(例如1 3 5 7排在1 3 6 8前面)。
数据范围
n>0 ,
0≤m≤n ,
n+(n−m)≤25
输入样例:
5 3
输出样例:
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
正解
(搜索)
- 1.通过上一道题目,我们知道这道题目利用了回溯的性质,也就是深度优先搜索
2.相比上一道题,本题应该注意的是,我们只需要选择m个数,并不是所有的数
3.回溯直接可以忽略不记,代码中有体现
C++ 代码
#include <bits/stdc++.h>
using namespace std;
int n,m,p[110];
void dfs(int x)
{
if (p[0]==m)
{
for (int j=1;j<=p[0];j++)
cout<<p[j]<<" ";
cout<<endl;
return ;
}
for (int i=x;i<=n;i++)
{
p[++p[0]]=i;
dfs(i+1);
p[p[0]--]=0;
}
}
int main()
{
cin>>n>>m;
dfs(1);
return 0;
}
正解二
#include <bits/stdc++.h>
using namespace std;
int n,m,p[110];
void dfs(int x)
{
if (p[0]==m)
{
for (int i=1;i<=p[0];i++)
cout<<p[i]<<" ";
cout<<endl;
return ;
}
if (x==n+1)
return ;
p[++p[0]]=x;
dfs(x+1);
p[p[0]--]=0;
dfs(x+1);
}
int main()
{
cin>>n>>m;
dfs(1);
}
正解三 位运算
#include <bits/stdc++.h>
using namespace std;
int n,m;
void dfs(int x,int now,int date)
{
if (x>n || date+(n-x+1)<m)
return ;
if (date==m)
{
for (int i=1;i<=n;i++)
if (now>>(i-1) & 1)
cout<<i<<" ";
puts("");
return ;
}
dfs(x+1,now+(1<<x),date+1);
dfs(x+1,now,date);
}
int main()
{
cin>>n>>m;
dfs(0,0,0);
}
大…大佬…,我看了20年终于看懂了0.0
为什么第一个是i+1呀,不可以x+1吗
大佬DFS的时间复杂度为多少?求解
那个时候佬还是个初中生呢
位运算的x>n为什么不是x==n
hell no。。。看呆了orz
‘为什么先选输出顺序就是正序?’有相同的疑问
搜索框架就是这样滴
因为一直不选的话首先dfs到的就是3
为什么先选输出顺序就是正序?
你之前发过,我看到了,然后点击提交评论,然后就404了,话说我看到了,肯定是会马上回的,不用这么激动辣
请问一下大佬, dfs(x+1,now+(1<<x),date+1);,这句话中的(now+(1<<x) )是什么意思呢?
x表示现在正在查找的第x个数, data为 找到的数的个数,那么now应该就是现在找到的数对吗?
是的,其实你用数组存储也是可以的
好的,谢谢大佬。
ps:突然发现自己发了好多重复评论,很尴尬(现在已删除);
想死,,真够变态的
那么,有没有非递归算法
日后补充吧