自学的dfs之数的划分

题目描述

将整数n分成k份,且每份不能为空,任意两份不能相同(不考虑顺序)。

例如:n=7,k=3,下面三种分法被认为是相同的。

{1,1,5};{1,5,1};{5,1,1};

问有多少种不同的分法。 输出一个整数,即不同的分法。

输入格式

两个整数n,k(6<n≤200,2≤k≤6),中间用单个空格隔开。

输出格式

一个整数,即不同的分法。

样例输入

7 3

样例输出

4
#include<iostream>
#include<algorithm>
using namespace std;
int n,k;//数n,分成k份
int stack[7];//存每份分到的数
int sum=0;//计方案数
void dfs(int cnt)
{
    if(n==0) return;//n代表的是剩下的数,(当cnt==k时,n==0时,为递归出口)
    if(cnt==k){//为了分法不重,我们采用升序进行,(即最后一位数比前一位数大,就可以选择)
        if(n>=stack[cnt-1])  sum++;
        return;
    }
    for(int i=stack[cnt-1];i<=n/(k-cnt+1);i++){//对范围进行了一丢丢剪枝操作
        //从【前一个数】到【剩下的数的平均数】之间进行选择数进行划分
        //因为后一位可以和前一位相等(不下降上升),所以我们从cnt-1开始
        //k-cnt+1代表的是我们还需要选的数的个数,n代表的是剩下的数。
        //n/(k-cnt+1)代表的是剩下要选的数的平均数
        stack[cnt]=i;//第cnt个数划分为i
        n=n-i;//剩下的数总数减i
        dfs(cnt+1);//下一个数的选择
        n=n+i;//回溯
    }
}
int main()
{
    cin>>n>>k;
    stack[0]=1;//从1开始累加或者说选数划分
    dfs(1);//从第1个开始选数,选k个
    cout<<sum<<endl;
    return 0;
}

        这里我需要取k个数,并且他们的和为n,主要的是他们的数据没有那么大,那么使用dfs的深搜的话就比较快。

        这里取数在考虑不重复的情况下,设定k个数之中,最后一个数最大。

        在深搜过程中,n在减小,stack[cnt]在增加,满足条件n>=stack[cnt-1]时,n==4,stack[cnt-1]==3,就可以考虑一个满足条件的k个数了,假如没有这个条件,再一次的dfs(1)会陷入死循环了

        不满足上面两个if条件语句的话,进入for语句i=stack[cnt-1],n-=i,此时的n就是剩下的和,再次进入dfs中,一旦满足if语句,就跳出dfs,并且n开始回溯,一直到n=6,此时继续开始for语句i=stack[cnt-1]+1,继续进入dfs循环之中。

        总而言之,dfs的深搜原理就是:

 void dfs(int x){

        判断条件,跳出当前的递归

        标记函数或者数组,代表这里已经被检查过了

        for循环 {

                dfs(x+1)

        }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值