NYOJ 32 组合数

组合数

时间限制: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;  
}  

 

原文地址:https://www.cnblogs.com/wshyj/p/6431503.html