面试经典动态规划,n个相同火柴分堆
来源:互联网 发布:深度卸载mac上的软件 编辑:程序博客网 时间:2024/05/16 18:35
题目描述:
现在有n个相同火柴,将这些火柴分成若干堆,问所有的分法总数。
题目分析:
初见题目第一反应是采用组合数学的方法来计算,有种叫Stirling数的组合数。他表示将n个不同物品分到k堆里,注意这里是n个不同物品,所以不能采用stirling数。
那么我们简单的做几个尝试好了,假设n=4,那么可以分如下几种:
4
1,3和 3,1算一种
2,2
1,1,2和 1,2,1 和 2,1,1算一种
1,1,1,1
这5个序列看似没有规律,但是我们还是能找出规律的,(1)中最大堆的根数是4,其他堆的总和是0;(2)中最大堆的根数是3,
其他堆的总和是1;(3)(4)中最大堆的根数是2,其他堆的总和是2,其他堆中的最大也不超过2;(5)中最大堆的根数是1,其他堆的
根数的总和是3,其他堆的最大根数也不超过1。
所有的情况综合起来就是:4个火柴分堆,有可能最大堆的根数是4,其他堆的总和是0,最大根数也是4。或者最大堆的根数不是4
而是3,就属于n个火柴分堆,但最大堆的根数不超过3这种情况了。然后依次类推。
所以可以总结递推公式是dp(n,k) = dp(n-k,k) + dp(n,k-1)。这里n是火柴总数,k表示分堆时最大堆的根数是k。dp(n,k)表示所有分
法的总数,dp(n-k,k)表示确实有分出去一个堆,该堆的根数是k的所有分法,那么剩下还没有分的火柴是n-k根。dp(n,k-1)表示,所有
没有堆的根数到达k(就是所有堆的根数都<=k-1)的所有分法。
那么我们的目标就是求dp(n,n)。在此我们添加边界条件,dp(0,i) = 1,i >= 0;dp(j,0) = 0, j > 0;
伪代码:
for(i = 0; i <= n; .i++)dp[0][i] = 1;
for(j = 1; j <= n ; j++)dp[j][0] = 0;
for(i = 1; i <= n ; i++)
for(j = 1; j <= i; j++)
{
int tmp = 0;
if(i - j > j)tmp = dp[i-j][di-j];
else tmp = dp[i-j][j];
dp[i][j] = tmp + dp[i][j - 1];
}
- 面试经典动态规划,n个相同火柴分堆
- 面试经典动态规划问题
- m个工厂分的n个资源,使获得利润最大(动态规划)
- 程序员面试金典: 9.9 递归和动态规划 9.8求n分可以由25分,10分,5分,1分的硬币的表示方法
- m个苹果分在n个相同的盒子
- 100个经典的动态规划方程
- 100个经典的动态规划方程
- [中等] 动态规划经典-堆石子问题
- n个盘子放m个苹果(动态规划)
- 《面试--动态规划》 ---五种经典的算法问题
- (11)分苹果问题:将m个相同的苹果放到n个相同的盘子中,多少钟分法?
- 分糖果(动态规划)
- 动态规划:分硬币
- 动态规划之n个元素出栈顺序种数
- 简单记录N个动态规划的例子
- 动态规划解N个矩阵链乘问题
- 动态规划 problem N
- 动态规划经典题目
- Spring常用注解
- 微信小程序开发手记之二:属性display
- 无法解析的外部符号
- Thread.currentThread().getName() ,对象实例.getName() 和 this.getName()区别
- CSDN 绑定手机号
- 面试经典动态规划,n个相同火柴分堆
- OSGi的作用
- LoadRunner常见问题
- Android获取短信验证码并自动填充的两种方式
- flask_mail的坑
- 友盟消息推送 3.x 的坑爹问题 s=-11,s1=accs bindapp error
- OracleSugar ORM框架的诞生,代码开源
- Linux 查找文件并删除掉
- SpringBatch详解