整数划分的dfs和dp

本文深入探讨了整数划分问题,包括使用深度优先搜索(DFS)和动态规划(DP)解决该问题的方法。通过实例说明如何将一个正整数划分成多个数的和,并提供了详细的代码实现。

整数划分问题是将一个给定的正整数划分成多个数的和,如给定5,划分的结果如下所示,注意这里将重复的划分剔除了。
比如5=1+1+1+2=1+1+2+1=1+2+1+1=2+1+1+1只保留了第一个。
5 = 1+1+1+1+1
5 = 1+1+1+2
5 = 1+1+3
5 = 1+2+2
5 = 2+3
5 = 1+4
5 = 5

dfs代码如下:

int ans[100], cnt; 
//ans数组记录每次选取的数,cnt记录总的划分数
//n:参与划分的目标, k:现在选取第几个, ns保证下一个选取不小于当前值
//当n = 0时,表明n已经被瓜分完,因此这里可以输具体划分方案
void dfs(int n, int k, int ns){ 
	if (n == 0){    
		printf("%d: ", ++cnt);
		for (int i = 1; i < k; i++) 
			printf("%d ", ans[i]);
		printf("\n");
	}
	else for (int i = ns; i <= n; i++){
		if (i <= n){
			ans[k] = i;
			dfs(n - i, k + 1, i);
		}
	}
}

dp代码如下:

int dp(int n, int m){
	if (m == 1 || n == 1) //m = 1|| n == 1 仅有一种分发
		return 1;	
	if (n == m) //n == m, 如果划分包含m则就1种,否则最大值就是m-1,所以dp(n, m - 1)
		return 1 + dp(n, m - 1);
	if (n < m)  //n < m, 大于n的部分都不可能参与划分,所以dp(n, n)
	 	return dp(n, n);		
	if (n > m)  //n > m分为包含m和不包含m
		return dp(n - m, m) + dp(n, m - 1); 
}

当然dfs也可以指定拆分的数字

int ans[100], cnt, m[5] = { 0, 1, 3, 4, 7 };
void dfs(int n, int k, int ns){ 
	if (n == 0){
		printf("%d: ", ++cnt);
		for (int i = 1; i < k; i++)
			printf("%d ", ans[i]);
		printf("\n");
	}
	else for (int i = 1; i <= 4; i++){
		if (m[i] <= n && ns <= m[i]){
			ans[k] = m[i];
			dfs(n - m[i], k + 1, m[i]);
		}
	}
}

指定数字的整数划分实际就是找零钱问题,这里就是要将给定的n元,使用1、3、4、7四种面额的所有方法,当然如果要求最小,只需要稍微处理即可。

下面这篇博客对整数划分做了较为全面的总结:https://blog.youkuaiyun.com/u011889952/article/details/44813593

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Researcher-Du

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值