zoukankan      html  css  js  c++  java
  • ybt1317 组合方案(dfs经典例题)超硬核

    ybt1317 组合输出

    dfs(深搜)例题

    【题目描述】

    排列与组合是常用的数学方法,其中组合就是从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
    

    【题解】

    分析数据范围,1<=r<n<21,根据组合公式:

    [C^r_n=frac {n!}{r!(n-r)!} ]

    可知,如果n取最大值20,那么方案数将是:

    [frac {2432902008176640000}{r!(20-r)!} ]

    画出图像后,发现图像过r=10对称,r=10时取到最大值184756。

    每个方案会有最多19个元素,共有19*184756=3510364个元素。

    dfs的复杂度为大约O(3.5*10^6^),可以接受。

    我一开始的代码出了许多问题,经过我的辛苦努力,最后还是AC了,看来想算法远不如实现算法困难:

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,r,ans[30];
    void dfs(int at,int x) {//at表示当前要判断的位,x表示上一位的数字(这一位的数字要从x之后找)
    	for(int i=x+1;i<=n;i++) {//枚举at位所有可行的数字
    		ans[at]=i;//赋值
    		if(at==r) {//位数已经足够,可以输出
    			for(int j=1;j<=r;j++){
    				printf("%3d",ans[j]);//格式
    			}
    			cout<<endl; 
    		}
    		else{
    			dfs(at+1,i);//当前位不是最后一位,继续dfs,以i为当前位,也就是at+1位的上一位
    		}
    	}
    	return;
    }
    int main() {
    	cin>>n>>r;
    	dfs(1,0);//共同的起点:当前位是第1位,上一位(第零位)值是0
    	return 0;
    }
    

    (本来调试时把第10行printf里的ans[j]打成ans[i],并且把第22行的dfs(1,0)打成dfs(0,0),样例过不了吓得我认为自己连例题都要借鉴题解)

    但是我终于自己打出来此题,祝贺一下!!

  • 相关阅读:
    Node.js、vue.js的使用
    windows配置环境变量
    http常见状态码及其解析
    AWS使用教程
    免费服务器集锦 免费服务器大全 免费使用服务器
    免费服务器AWS免费使用一年详细教程
    PHP实现RSA2加密
    dcoker安装redis
    ES,kibana通过nginx添加访问权限
    docker快速安装kibana
  • 原文地址:https://www.cnblogs.com/Wild-Donkey/p/12234332.html
Copyright © 2011-2022 走看看