#10018. 「一本通 1.3 例 1」数的划分(深搜剪枝详解)

数的划分

题目描述
将整数 n 分成 k 份,且每份不能为空,问有多少种不同的分法。当 n=7,k=3 时,下面三种分法被认为是相同的:1,1,5 ; 1,5,1 ; 5,1,1
输入格式
一行两个数 n , k。
输出格式
一行一个整数,即不同的分法数。
样例输入

7 3

样例输出

4

样例解释
四种分法为:1,1,5 ;1,2,4 ;1,3,3 ;2,2,3

数据范围与提示

6<=n<=200
2<=k<=6

代码中有详细解答

AC代码:

#include<stdio.h>
typedef long long ll;
int n,m,a[16],s=0;//a数组里面储存的是分成的每一份的数,s代表的是不同分法的个数
void dfs(int k)
{
    
    
	int i;
	if (n==0)//n代表的是剩下的数,(当k==m时,n==0,说明n没法选了,要返回。)
		return;
	if (k==m)//k代表的是多少份
	{
    
    
		if (n>=a[k-1])//为了分法不重,我们采用升序进行,(即最后一位数比前一位数大,就可以选择)
			s++;
		return;
	}
	for (i=a[k-1]; i<=n/(m-k+1); i++)//因为后一位可以和前一位相等,所以我们从k-1开始
	{
    
    
		//m-k+1代表的是我们还需要选的数的个数,n代表的是剩下的数。n/(m-k+1)代表的是剩下要选的数的平均数
		a[k]=i;
		n=n-i;//把选过的数减去
		dfs(k+1);//进行下一位选择
		n=n+i;//回溯
	}
}
int main()
{
    
    
	scanf("%d%d",&n,&m);
	a[0]=1;//我们从1开始选数
	dfs(1);//要选m个数,所以我们从第一位开始选择
	printf("%d\n",s);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zlzqq/article/details/109297004