• 组合的输出


    问题 G: 【例5.2】组合的输出

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 51  解决: 33
    [提交][状态][讨论版][命题人:quanxing]

    题目描述

    排列与组合是常用的数学方法,其中组合就是从n个元素中抽出r个元素(不分顺序且r≤n),我们可以简单地将n个元素理解为自然数1,2,…,n,从中任取r个数。

    现要求你用递归的方法输出所有组合。

    例如n=5,r=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

    输入

    一行两个自然数n、r(1<n<21,1≤r≤n)。

    输出

    所有的组合,每一个组合占一行且其中的元素按由小到大的顺序排列,每个元素占三个字符的位置,所有的组合也按字典顺序。

    样例输入

    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


    解题思路:递归搜索。开一个数组vis用来标记每个数是否已经使用,为了保持从小到大输出,每次递归后for循环从上一次保存的数+1开始搜索。
    #include <bits/stdc++.h>
    using namespace std;
    
    int n,r,a[25];
    bool vis[25];//来记录各个数字是否被访问
    
    void dfs (int dep)//dep代表搜索的深度,即当前数组a添加了多少个数
    {
        for (int i=a[dep-1]+1;i<=n;++i)//从上一个添加的数+1开始搜索数字
        {
            if (!vis[i])//如果这个数字没被访问过
            {
                a[dep]=i;//将这个数字添加到a里面去
                if (dep==r)//如果添加的数字达到r个,把他们输出
                {
                    for (int j=1;j<=r;++j)
                    printf("%3d",a[j]);
                    printf("
    ");
                }
                else
                dfs(dep+1);//如果达不到r个继续添加
                vis[i]=0;//回溯,清空当前状态,把vis[i]设为没有访问过。
            }
        }
    }
    
    int main()
    {
        while (~scanf("%d%d",&n,&r))
        {
            memset(a,0,sizeof a);
            memset(vis,false,sizeof vis);
            dfs(1);//从第一个数开始搜索
        }
        return 0;
    }
    

      

  • 相关阅读:
    超实用的 Nginx 极简教程,覆盖了常用场景(转)
    阿里云Redis开发规范(转)
    什么是 AQS ?
    缓存穿透、缓存并发、缓存失效之思路变迁(转)
    看不懂JDK8的流操作?5分钟带你入门(转)
    Redis 分布式锁的正确实现方式(转)
    urllib-Proxy
    基本urllib库
    Windows DOS 命令(持续更新...)
    java 位运算符
  • 原文地址:https://www.cnblogs.com/wjw2018/p/9286731.html
Copyright © 2020-2023  润新知