DFS排列组合

初学,加强一下理解

#include<iostream>
using namespace std;
int n,r,a[100],b[100];

/* 每次dfs都是从1到n中
   选出一个数放在排列中第x个位置
*/
void dfs(int x)
{
    if(x==r+1)   //截止条件,只需要放r个数,当递归到第r+1时,则停止,并输出已经排好的r个数
    {
        for(int i=1;i<=r-1;i++)
            cout<<a[i]<<" ";
            cout<<a[r];
        cout<<endl;
        return;
    }
    for(int i=1;i<=n;i++)
    {
        if(b[i]==0&&i>a[x-1])    //  第i个数是可用的,且保证不再重复
        {
            a[x]=i;    //  将这个数放到x这个位置
            b[i]=1;    //  则这个数不能再使用了
            dfs(x+1);  //  往排列的下一个位置
            b[i]=0;    //  回溯
            /*
               比如在三个数中选三个数做排列
               则刚开始,dfs(1)在i=1时进入dfs(2),dfs(2)在i=2时进入dfs(3),
               dfs(3)在i=3时进入dfs(4)则可以输出一次结果,dfs(4)结束,
               此时回到dfs(3),则b[3]=0,表明第三个数是可用的
               而此时for循环也到了3,则dfs(3)结束,
               回到dfs(2)中进入dfs(3)的地方,此时i=2,则b[2]=0,表明第二个数也可用
               此时dfs(2)则表明还在尝试第二个位置能不能放其他的数,
               for循环继续,i为3,发现第三个数可用,则放上第三个数,进入dfs(3),发现第二个数可用,放上
               进入dfs(4),则输出另一个结果
            */
        }
    }
}
int main(void)
{
    cin>>n>>r;
    for(int i=1;i<=n;i++)
    {
        b[i]=0;
    }
    for(int i=1;i<=r;i++)
    {
        a[i]=0;  //放排列数
    }
    dfs(1);
}

关于回溯:我们可以以一个1到3的全排列为例,则全排列过程可以想象为你穿过三层墙,每层墙都有三个编号为1、2、3的门,穿过每层墙时只能选一道门,且不能选择你之前已经走过的门的编号,则每次dfs都是选择门编号的过程,dfs()括号中的参数表示当前经过第几道墙,dfs中for循环则表示遍历三道门的编号,如果可用,则选择这道门进入,并且进行下一层墙的选择即dfs(x+1),注意此时并不会继续运行b[i]=0的代码,而是要等dfs运行完找到了出路或者走不下去本层dfs才会运行到b[i]=0,此时的i的值即为本层dfs也即本层墙选择的门编号,则下一次回到这里时将不再选择这道门,所以要将b[i]设置为0,继续for循环看是否有其他门可用

for(int i=1;i<=n;i++)
    {
        if(b[i]==0)  
        {
            a[x]=i;   
            b[i]=1;    
            dfs(x+1);  
            b[i]=0;   
        }
    }

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值