zoukankan      html  css  js  c++  java
  • AcWing 93.递归实现组合型枚举

    链接:https://www.acwing.com/problem/content/description/95/
    题目:
    从 1∼n 这 n 个整数中随机选出 m 个,输出所有可能的选择方案。

    输入格式
    两个整数 n,m ,在同一行用空格隔开。

    输出格式
    按照从小到大的顺序输出所有方案,每行 1 个。

    首先,同一行内的数升序排列,相邻两个数用一个空格隔开。

    其次,对于两个不同的行,对应下标的数一一比较,字典序较小的排在前面(例如 1 3 5 7 排在 1 3 6 8 前面)。

    数据范围
    n>0 ,
    0≤m≤n ,
    n+(n−m)≤25
    输入样例:
    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
    思路:
    同样是采用dfs的方式从第一位到最后一位枚举。但因为是组合型,没有顺序差别,所以需要筛选。
    如果规定从前往后枚举时每一个数都必须比前面一个数大,最后是递增的关系,那么组合型枚举就可以实现。
    比如:1,3,5这三个数,在枚举时可能有135,153,315,351,513,531这六种情况,如果按照递增顺序枚举,那么只有一种情况会保留下来,也就是135,这样就可以避免重复枚举。
    在枚举时传入参数start(从哪个数开始枚举),可以实现从小到大枚举。
    剪枝思路:如果一种情况一定无解,就不需要再运算,直接剪去。
    当还需要枚举的数的数量大于还剩下可以枚举的数的数量时,一定无解。
    m-u+1>n-start+1,即m-u-n+start>0;

    可以看到运行时间快了将近三倍
    题解:

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=30;
    int n,m;
    int ans[N]; 
    
    void dfs(int u,int start)
    {
    	if(m-u-n+start>0) return; //剪枝,剪去一定无解的分支 
    	if(u>m)  //m个数已选择完毕 
    	{
    		for(int i=1;i<=m;i++)
    			cout<<ans[i]<<' ';
    		cout<<endl;
    		return;
    	}
    	for(int i=start;i<=n;i++)
    	{
    		ans[u]=i;  
    		dfs(u+1,i+1);
    		ans[u]=0;   //恢复现场
    	}
    	return;
    }
    
    int main()
    {
    	cin>>n>>m;
    	dfs(1,1);
    	return 0; 
    }
    
  • 相关阅读:
    SQL Server中跨服务器跨数据库之间的数据增删改查
    Tomcat部署项目的方法
    java的位运算
    手机和邮箱格式验证
    Java实现List中某个对象属性中的字符串参数首字母进行排序
    springboot+dubbo+ZooKeeper+mybatis搭建分布式项目
    Java爬页面数据
    判断指定日期是否为节假日、双休日、工作日
    Java代码ping ip工具类
    Java生成压缩文件(zip、rar 格式
  • 原文地址:https://www.cnblogs.com/longwind7/p/15569744.html
Copyright © 2011-2022 走看看