三种递归(指数,排列,组合)

指数型枚举

体积 - 小志61314 - 博客园 (cnblogs.com)

每一个数可以分为选和不选的两种情况,这也是一个状态空间了,总共两种情况,可以依次枚举每个数选还是不选,正好做到不重不漏。
首先找到问题的边界,由原问题出发到边界,一层层扩展
每个数选还是不选
一开始每个数都不选,然后到边界每个数都需要经历过选还是不选,这是一个大类,在一个数选择了基础上,下面的依次是选还是不选,(这个地方看代码,下面的递归开始的时候,自然进入到不选的那个递归,直到边界)然后回溯就开始依次选上了,不要忘记还原现场
下面看代码吧

#include<iostream>
#include<vector>
using namespace std;
vector<int> v;
int n;
void dfs(int u) 
{
    if(u==n+1)
    {
        for(int i=0;i<v.size();i++)
            cout<<v[i]<<" ";
        cout<<endl;
        return ;
    }
    dfs(u+1);
    v.push_back(u);
    dfs(u+1);
    v.pop_back();
}
int main(){
    cin>>n;
    dfs(1);
    return 0;
}

组合型递归:

谷仓的安保 - 小志61314 - 博客园 (cnblogs.com) 这个是组合型例题

数的划分 - 小志61314 - 博客园 (cnblogs.com)类似的剪枝方法

可以在指数型基础上加入剪枝,因为组合型要求顺序不变,刚好指数型是每一个分支,没有重复的,再在剪枝的基础上加入m变量就可以了

#include<iostream>
#include<vector>
using namespace std;
int n,m;
vector<int> v;
void dfs(int u,int cnt)
{
    if(v.size()>m||v.size()+n-u+1<m) return ;
    if(u==n+1&&cnt==m)
    {
        for(int i=0;i<v.size();i++)
            cout<<v[i]<<" ";
        cout<<endl;
        return ;
    }
    cnt++;
    v.push_back(u);
    dfs(u+1,cnt);
    cnt--;
    v.pop_back(); 
    dfs(u+1,cnt);
}
int main(){
    cin>>n>>m;
    dfs(1,0);
    return 0;
} 

还有一种就是完全不同的搜索方法

按照字典序从小到大排列且没有重复,直接定义一个start,保证后面的数全部比start大即可

#include<iostream>
using namespace std;
int n,m;
const int N=50;
int p[N];
void dfs(int u,int start)//第二个保证了是以start开始,以确保不会重复 
{
    if(u==m+1)
    {
        for(int i=1;i<=m;i++)
            cout<<p[i]<<" ";
        cout<<endl;
        return ;
    }
    for(int i=start;i<=n;i++)
    {
        p[u]=i;
        dfs(u+1,i+1);
    }
}
int main(){
    cin>>n>>m;
    dfs(1,1);
    return 0;
}

 排列型递归:

带分数 - 小志61314 - 博客园 (cnblogs.com) 排列型的应用,不过用到了STL的函数(可以不用手搓长代码了QAQ)

#include<iostream>
using namespace std;
const int N=50;
int n;
int p[N];
bool st[N];//判重,不能有重复 
void dfs(int u)
{
    if(u==n+1)
    {
        for(int i=1;i<=n;i++)
            cout<<p[i]<<" ";
        cout<<endl;
        return ;
    }
    for(int i=1;i<=n;i++)
    {
        if(!st[i])
        {
            st[i]=true;//填
            p[u]=i;
            dfs(u+1);//下一层再填数
            st[i]=false;//回溯,还原现场
        }
    }
}
int main(){
    cin>>n;
    dfs(1);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值