组合数
时间限制:3000 ms | 内存限制:65535 KB
难度:3
- 描述
- 找出从自然数1、2、... 、n(0<n<10)中任取r(0<r<=n)个数的所有组合。
- 输入
- 输入n、r。
- 输出
- 按特定顺序输出所有组合。
特定顺序:每一个组合中的值从大到小排列,组合之间按逆字典序排列。 - 样例输入
-
5 3
- 样例输出
-
543 542 541 532 531 521 432 431 421 321
做法:回溯(深搜 DFS) 介绍:http://blog.chinaunix.net/uid-26602509-id-3178938.html
我们要求的递推函数功能应该是 f(6,3,a)能打印出所有最大数为6 位数为3 从大到小排列的数
f(5,2,a)能打印出所有最大数为5 位数为2 从大到小排列的数
本题使用了递归:设f(6,3,a)表示在6个自然数中选三个从大到小排列的数(即n=6 r=3) a用来存储选出的三个数
f(6,3,a)= 循环(首位为i(i=6) + f(5,2,a) + 输出数组 + 然后首位减1 )
f(5,2,a) = 循环(首位为i(i=5) + f(5,2,a) + 输出数组 + 然后首位减1 )
f(4,1,a) = 循环(首位为i(i=4) + 输出数组 + 然后首位减1 )
归纳起来就是 f(n,r,a) = (a[r-1]=n) + f(n-1,r-1,a) ------r>1
f(n,r,a) = (a[r-1]=n) + 打印数组a ------r=1
#include<iostream> using namespace std; void DFS(int n, int r,int a[]) // { for(int i = n; i > 0; i--) //最外面的循环是为了实现 最后一位数的变化 比如654 653 652 651 { //一个循环出现n个子递归函数结果 比如f(4,1,a)出现4 3 2 1四种结果 a[r] = i; //然后4递归回去 出现54 3递归回去出现54 43 .。。。。。。。。 if(r > 1) //、、、、 { DFS(i-1,r-1,a); } else { for(int i = a[0]; i > 0; i--) //打印搜索的结果 a[0]表示位数 { cout<<a[i]; } cout<<endl; } } } //因为i-1的存在 就已经保证了从大到小排列的约束条件 所以每一个小于等于n的数都是符合条件的 原循环通过从大到小实现 int main() { int n,r; int a[11]; cin>>n>>r; a[0] = r; DFS(n,r,a); return 0; }