整数划分问题-解法汇总(暂有DP-递归)
整数划分问题是一个锻炼组合数学,递归以及动态规划很好的例子,虽然问题看似简单,但是其中玄机万千,有人转化成为背包问题,有人用生成函数解,有人以此作为企业面试题目,可见这种问题的认可度还是很高的。
整数划分问题可以出现很多变种问题:
1. 将n划分成若干正整数之和的划分数。(原题)
2. 将n划分成k个正整数之和的划分数。
3. 将n划分成最大数不超过k的划分数。
4. 将n划分成若干奇正整数之和的划分数。
5. 将n划分成若干不同整数之和的划分数......
第2,3,5的Code在北大研究生推免机试(校内)-复杂的整数划分中放出
具体来说,什么是整数划分呢?
- 假设有一个整数 n , 总存在 n=m1+m2+...+mi; (mi为正整数,且1 <= mi <= n),则{m1,m2,...,mi}为n的一个划分。
∞这里我先用动态规划和递归的思想来解答该问题:
- 我们定义一个状态如下: 当max(m1,m2,...,mi)<=m,那么称这一状态属于n的一个m划分。这里我们记n的m划分的个数为f(n,m);
- 举个例子,当n=5时我们可以获得以下这几种划分(注意,例子中m>=5)
5 = 5 ————f(5,5)
= 4 + 1 ————f(5,4)
= 3 + 2 |
= 3 + 1 + 1 ————f(5,3)
= 2 + 2 + 1 |
= 2 + 1 + 1 + 1 ————f(5,2)
= 1 + 1 + 1 + 1 + 1 ————f(5,1)
根据n和m的关系,考虑以下几种情况:
1. 当n=1时,只有一种划分{1};
2. 当m=1时,只有一种划分{1,1,1,...,1};
3. 当n=m时,根据划分中是否包含n,可分为两种情况:
(1) 划分中包含n的情况,只有一个即{n};
(2) 划分中不包含n的情况,这时划分中最大的数字也一定比n小,即n的所有(n-1)划分。
因此 f(n,n) =1 + f(n,n-1);
4. 当n<m时,划分总等同于f(n,n);
5. 但n>m时,根据划分中是否包含最大值m,可以分为两种情况:
(1) 划分中包含m的情况,即{m, {x1,x2,...xi}}, 其中{x1,x2,...xi} 的和为n-m,由于m>n-m,因此是(n-m)的m划分,因此这种划分个数为f(n-m, m);
(2) 划分中不包含m的情况,则划分中所有值都比m小,即n的(m-1)划分,个数为f(n,m-1);因此 f(n, m) = f(n-m, m)+f(n,m-1);
综合以上情况,我们可以看出,上面的结论具有递归定义特征,其中(1)和(2)属于回归条件,(3)和(4)属于特殊情况,将会转换为情况(5)。
而情况(5)为通用情况,属于递推的方法,其本质主要是通过减小m以达到回归条件,从而解决问题。其递推表达式如下:
- f(n, m)= 1; (n=1 or m=1)
- f(n, m)=f(n, n); (n<m)
- 1+ f(n, m-1); (n=m)
- f(n-m,m)+f(n,m-1); (n>m)
依照上述解法,就能够写出如下Code了:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std; #define MAX 51 int dp[MAX][MAX]; void DP()
{
for (int n = ; n < MAX; n++)
{
for (int m = ; m < MAX; m++)
{
if (n < m)
dp[n][m] = dp[n][n];
else if (n > m)
dp[n][m] = dp[n - m][m] + dp[n][m - ];
else
dp[n][m] = + dp[n][m - ];
}
}
} int main()
{
int num; //输入整数
DP();
while (scanf("%d", &num) != EOF)
printf("%d\n", dp[num][num]); return ;
}
小墨-原创
其他变种:
1.将n划分成不大于m的划分法:
1).若是划分多个整数可以存在相同的:
dp[n][m]= dp[n][m-1]+ dp[n-m][m]
dp[n][m]表示整数 n 的划分中,每个数不大于 m 的划分数。
则划分数可以分为两种情况:
a.划分中每个数都小于 m,相当于每个数不大于 m- 1, 故划分数为 dp[n][m-1].
b.划分中有一个数为 m. 那就在 n中减去 m ,剩下的就相当于把 n-m 进行划分, 故划分数为 dp[n-m][m];
2).若是划分多个不同的整数:
dp[n][m]= dp[n][m-1]+ dp[n-m][m-1]
dp[n][m]表示整数 n 的划分中,每个数不大于 m 的划分数。
同样划分情况分为两种情况:
a.划分中每个数都小于m,相当于每个数不大于 m-1,划分数为 dp[n][m-1].
b.划分中有一个数为 m.在n中减去m,剩下相当对n-m进行划分,
并且每一个数不大于m-1,故划分数为 dp[n-m][m-1]
3).将n划分成k个数的划分法:
dp[n][k]= dp[n-k][k]+ dp[n-1][k-1];
方法可以分为两类讨论:
第一类: n 份中不包含 1 的分法,为保证每份都 >= 2,可以先拿出 k 个 1 分
到每一份,然后再把剩下的 n- k 分成 k 份即可,分法有: dp[n-k][k]
第二类: n 份中至少有一份为 1 的分法,可以先拿出一个 1 作为单独的1份,剩
下的 n- 1 再分成 k- 1 份即可,分法有:dp[n-1][k-1]
4).将n划分成奇正整数的划分法:
只需将1)中第二重循环的m++改成m+=2,因为 <=某偶数 和 <= 某偶数-1 是相同的描述
- 以上三种的代码在北大2014研究生推免机试(校内)-复杂的整数划分中放出
整数划分问题-解法汇总(暂有DP-递归)的更多相关文章
- hdu1028(整数划分问题)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1028 整数划分问题 整数划分 --- 一个老生长谈的问题: 描述 整数划分是一个经典的问题.请写一个程 ...
- noi 7219:复杂的整数划分问题
7219:复杂的整数划分问题 查看 提交 统计 提问 总时间限制: 200ms 内存限制: 65536kB 描述 将正整数n 表示成一系列正整数之和,n=n1+n2+…+nk, 其中n1>= ...
- noi7219 复杂的整数划分问题
noi7219 复杂的整数划分问题 #include <bits/stdc++.h> using namespace std; ; int dp1[maxn][maxn], dp2[max ...
- poj 3181 Dollar Dayz (整数划分问题---递归+DP)
题目:http://poj.org/problem?id=3181 思路:将整数N划分为一系列正整数之和,最大不超过K.称为整数N的K划分. 递归:直接看代码: 动态规划:dp[i][j]:=将整数i ...
- 区间dp 整数划分问题
整数划分(四) 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 暑假来了,hrdv 又要留学校在参加ACM集训了,集训的生活非常Happy(ps:你懂得),可是他最近 ...
- 整数划分问题(记忆化搜索和DP方法)
一. 问题 现在有一正整数N,要把它分为若干正整数之和,问有多少种本质不同的分法? (1)其中最大数不超过m, 有多少种分法? (2)分割后的正整数的数目不超过m个, 有多少种分法? (3)分成最大数 ...
- 华为OJ平台——放苹果(典型整数划分问题)
题目描述: 输入m,n,分别表示苹果数与盘子的总数,要求输出苹果放在n个盘子的方法总数(注意511和151是一种情况),例如输入 7 3 输出8((7),(6,1),(5,2),(4,3),(5,1, ...
- 【noi 2.7_7219】复杂的整数划分问题(算法效率)
题意:若干组数据,分别问 N划分成K个正整数之和的划分数目.N划分成若干个不同正整数之和的划分数目.N划分成若干个奇正整数之和的划分数目. 解法:请见我之前的一篇博文内的Article 2--[noi ...
- 【noi 2.7_7215】简单的整数划分问题(算法效率)
题意:问正整数n的所有划分个数. 解法:f[i][j]表示划分 i 后的每个数不大于 j 的划分数.分情况讨论:划分中每个数都小于 j,相当于每个数不大于 j- 1, 故划分数为 f[i][j-1] ...
随机推荐
- APACHE POI教程 --java应用程序用POI与Excel交互
POI报表 --用POI与Excel交互 AURISOFT 第一章 POI简介 --Jakata Poi HSSF:纯java的Excel解决方案 在我们实际的开发中,表现层的解决方案虽然有多样,但是 ...
- 新浪微博客户端(50)-解决输入Emotion表情逐渐变小的问题
UITextView+Extension.h #import <UIKit/UIKit.h> @interface UITextView (Extension) /** 插入属性文本 */ ...
- [git]添加项目到git
写在前面 一直在想把代码托管到git上面,一直没有去研究,最近发现自己写的demo,好多都找不到了,实在是没办法了,耐下心研究了下git.这里通过添加了自己做的demo,算是也是学习下git的操作吧. ...
- 15个初学者必看的基础SQL查询语句
本文由码农网 – 小峰原创翻译,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划! 本文将分享15个初学者必看的基础SQL查询语句,都很基础,但是你不一定都会,所以好好看看吧. 1.创建表和数据插 ...
- php后台多用户权限组思路与实现程序代码
网站开发少不了有网站后台,有了后台自然要对用户有同角色来分配一下,特别是多用户系统的情况下,如我一个系统要有多个管理员,那么我这些管理要分成,编辑,友情连接,管理员等,那我们要有权限和角色分配,今天我 ...
- oracle唯一索引与普通索引的区别和联系以及using index用法
oracle唯一索引与普通索引的区别和联系 区别:唯一索引unique index和一般索引normal index最大的差异是在索引列上增加一层唯一约束.添加唯一索引的数据列可以为空,但是只要尊在数 ...
- PostgreSQL表空间、数据库、模式、表、用户/角色之间的关系
看PostgreSQL9的官方文档,我越看越迷糊,这表空间,数据库,模式,表,用户,角色之间的关系怎么在PostgreSQL里这么混乱呢?经过中午的一个小实验,我逐渐理清了个中来龙去脉.下面我来还原我 ...
- 装X之读书籍
.读书又记不住...读过又有什么用...读万卷书 == 读0卷书 ? .额.读书不是记住的,毕竟哪里有这么多过目不忘的天才...要理解书中的内容...理解... .还是要记的,但是要理解的基础上记住. ...
- poj3070 Fibonacci
Description In the Fibonacci integer sequence, F0 = 0, F1 = 1, and Fn = Fn − 1 + Fn − 2 for n ≥ 2. F ...
- nginx命令
window cmd 到nginx的文件夹 start nginx 启动命令 nginx -s reload 重新启动 nginx -s stop 关闭 linux 到 sbin ...