题目32:组合数

来源:互联网 发布:本科 算法工程师 编辑:程序博客网 时间:2024/05/18 01:18

题目链接:

http://acm.nyist.net/JudgeOnline/problem.php?pid=32

描述

找出从自然数1、2、… 、n(0 < n < 10)中任取r(0<r≤n)个数的所有组合。

输入

输入n、r。

输出

按特定顺序输出所有组合。
特定顺序:每一个组合中的值从大到小排列,组合之间按逆字典序排列。

样例输入

5 3

样例输出

543
542
541
532
531
521
432
431
421
321

算法思想:

这个题目经典组合生成算法,经典组合生成算法如下图所示:
这里写图片描述
这道题所要求的是对输出进行简单的修改,将从小到大输出改为从大到小输出。所以,算法也需要做相应的修改。
首先,a[0…r]赋初值(最大值),并输出;
然后从右往左扫描a[0…r],查找第一个大于r - i的数,如果存在这样的数a[k],则将a[k]- -,并更新a[k]右边的数,a[j] = a[j - 1] + 1,j = k + 1,k + 2,…r。输出组合。
如果不存在,则说明组合已经完全生成,达到了最小值。

源代码

#include <iostream>using namespace std;void assemble(int n, int r){    int *a = new int[r];    for (int i = 0; i < r; i++)    {        //赋值最大值,即初值        a[i] = n - i;        cout << a[i];    }    cout << endl;    for (int i = r - 1; i >= 0; i--)    {        //cout << "i = " << i << "," << "a[i] = " << a[i] << "," << "r = " << r << endl;        //从右往左扫描查找大于r - i的数,如果存在,则将其a[i]--,并更新a[i]后的数        if (a[i] > r - i)        {            a[i]--;            for (int j = i + 1; j < r; j++)            {                a[j] = a[i] - j + i;            }            for (int i = 0; i < r; i++)            {                cout << a[i];            }            cout << endl;            //回溯            i = r;        }    }}int main(){    int n, r;    cin >> n >> r;    assemble(n,r);    return 0;}