递归与递推

递归

所有递归都可以画递归搜索树来理解

例如斐波那契数列:

实现指数型枚举

例:从 1∼n 这 n 个整数中随机选取任意多个,输出所有可能的选择方案。

递归法:

#include<iostream>
#include<cstdio>

using namespace std;

const int N=18;
int st[N],n; //1选 0不选

void dfs(int u)
{
    if(u==n)
    {
        for(int i=0;i<n;i++)
            if(st[i]==1) printf("%d ",i+1);
        puts("");
        return ;
    }
    
    st[u]=0;
    dfs(u+1);
    st[u]=1;
    dfs(u+1);
}

int main()
{
    cin>>n;
    
    dfs(0);
    
    return 0;
}

二进制右移法:

#include<iostream>

using namespace std;

int main()
{
    int n;
    scanf("%d",&n);
    int v=1;
    for(int i=0;i<n;i++) v*=2;
	for(int op=0;op<v;op++)
	{
	    for(int i=0;i<n;i++)
	    {
	        if(op>>i&1) printf("%d ",i+1); 
	    }
	    puts("");
	}
	
	return 0;
}

实现排列型枚举

例:把 1∼n 这 n 个整数排成一行后随机打乱顺序,输出所有可能的次序

递归法:

#include<iostream>
#include<cstdio>

using namespace std;

const int N=11;
int way[N],st[N],n; //st 0可用 1不可用

void dfs(int u)
{
    if(u==n)
    {
        for(int i=0;i<n;i++)
            printf("%d ",way[i]);
        puts("");
        return;
    }
    
    for(int i=1;i<=n;i++)
    {
        if(st[i]==0)
        {
            way[u]=i;
            st[i]=1;
            dfs(u+1);
            st[i]=0;
        }
    }
}

int main()
{
    cin>>n;
    
    dfs(0);
    
    return 0;
}

函数法:

函数头文件<algorithm>

bool next_permutation(iterator start,iterator end)

next_permutation函数求当前排列的下一个排列,这里指按照字典序排列,不存在下一个排列时返回false

prev_permutation相反,求的是当前排列的上一个排列

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

using namespace std;

const int N=11;
int a[N];

int main()
{
    int n;
    cin>>n;
    
    for(int i=0;i<n;i++) a[i]=i+1;
    
    do
    {
        for(int i=0;i<n;i++) printf("%d ",a[i]);
        puts("");
    }while(next_permutation(a,a+n));
    
    return 0;
}

实现组合型枚举

例:从 1∼n 这 n 个整数中随机选出 m 个,输出所有可能的选择方案,保证方案为升序

剪枝法:

#include<iostream>
#include<cstdio>

using namespace std;

const int N=30;
int way[N],st[N],n,m;

void dfs(int u)
{
    if(u==m)
    {
        for(int i=0;i<m;i++) printf("%d ",way[i]);
        puts("");
        return;
    }
    
    for(int i=1;i<=n;i++)
    {
   	 if(n-i<m-u-1) return; //剪枝:剩下的n-i个数不足够填
        if(st[i]==0&&(i>way[u-1]||u==0)) //剪枝:不满足升序
        {
            way[u]=i;
            st[i]=1;
            dfs(u+1);
            st[i]=0;
        }
    }
}

int main()
{
    cin>>n>>m;
    
    dfs(0);
    
    return 0;
}
posted @ 2023-04-15 14:08  咕噜噜冒泡  阅读(12)  评论(0编辑  收藏  举报