AcWing 93. 递归实现组合型枚举(递归)

题目
关于时间复杂度的分析
y总的视频中讲到算出的数不超过1亿,一般不会超时。本题是C以25为底 13为上算出结果乘13 = 5200300(13就是本题的m)
因为还有输出,每个组合最多需要输出13次
最后答案*520030013= 67603900 **

自己超时的代码,虽然超时了,但是这是自己认真改写的,下次继续加油!
这是基于(AcWing 94 .递归实现排列型枚举 )题改写的,94题没有(每一行从小到大排序的规则)这题需要加上代码,使输出从小到大。
超时代码

#include<iostream>//注意本题是   字典排序 
#include<cstdio>//时间是    n!
#include<cstring>
#include<algorithm>
using namespace std;

const int N=10;

int n,m;
int state[N];// 0 表示还没放数,1~n表示放了哪个数
bool used[N]; // true表示用过,false表示还未用过

void dfs(int u)
{
    
    
	if(u>m) //  因为输出为m个,所以当u=m+1时就可以进行输出 
	{
    
    
		for(int i=1;i<m;i++)//!!!与94题不一样的地方,这里会去掉不是顺序的输出 
		{
    
    
			if(state[i+1]<state[i])
			{
    
    
				return;
			}
		}
			
		for(int i=1;i<=m;i++){
    
    // 打印方案
			printf("%d ", state[i]);
		}
		puts("");
		return ;
		}
	
	
	 // 依次枚举每个分支,即当前位置可以填哪些数
	for(int i=1;i<=n;i++){
    
    
		if(!used[i]){
    
    
			state[u]=i;
			used[i]=true;
			dfs(u+1);
			
			//恢复现场
			state[u]=0;
			used[i]=false; 
		}
	}
}

int main()
{
    
    
	scanf("%d %d",&n,&m);
	dfs(1);
	return 0;
}

y总代码
分析图:
在这里插入图片描述

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 30;

int n, m;
int state[N];//存储每次输出的数组 

void dfs(int u, int start)
{
    
    
    if (u-1 + n - start +1< m) return;  // 剪枝  (150->50ms)速度加快三倍  
    //每个数组最多可以输出(u-1 + n - start +1)个 ,如果它<m,这组数据已经不用再进行考虑了 (对应的是树中的!红错号)
    if(u>m) 
	{
    
    
        for (int i = 1; i <= m; i ++ ) printf("%d ", state[i]);
        puts("");
        return;
    }

    for (int i = start; i <= n; i ++ )//因为需要顺序输出,所以每次从start开始(对应第28行) 
    {
    
    
        state[u] = i;
        
        dfs(u + 1, i + 1);//与其他(递归)不同的是多了 i+1,因为这道题需要顺序输出,start每次都需要+1 
        state[u] = 0; // 恢复现场
    }
}

int main()
{
    
    
    scanf("%d%d", &n, &m);

    dfs(1, 1);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_47874905/article/details/114899496