• 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),样例过不了吓得我认为自己连例题都要借鉴题解)

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

  • 相关阅读:
    python实现斑马打印机网络打印
    深入理解Nginx-模块开发与架构解析(第2版)第二章
    深入理解Nginx-模块开发与架构解析(第2版)第一章
    Django Web应用开发实战附录A
    Django Web应用开发实战第十六章
    Django Web应用开发实战第十一章
    Django Web应用开发实战第七章
    Django Web应用开发实战第五章
    Django Web应用开发实战第四章
    2017-2018-2 20179213《网络攻防》第一周作业
  • 原文地址:https://www.cnblogs.com/Wild-Donkey/p/12234332.html
Copyright © 2020-2023  润新知