整数拆分,dp入门经典 |
您所在的位置:网站首页 › 整数拆分递归 › 整数拆分,dp入门经典 |
整数拆分
给定一个整数n,将其无序拆分成最大数为k的拆分数,(n,k不超出100) 要求:所有的拆分方案不重复。 如当n=4,k=4时,一共有5种拆分方案,拆分如下:
(1)4=1+1+1+1
(2)4=1+1+2
(3)4=1+3
(4)4=2+2
(5)4=4
输入格式:
每一行输入一组整数n,k,遇到键盘结束符^Z或文件结束符EOF时结束输入。 输出格式:按行输出每组的拆分方案数。 输入样例: 4,4 5,4 输出样例: 5 6 解题思路:题意:就是给你两个正整数n,k。然后把n拆分成若干个整数,且每个整数的最大值不能大于k。而且拆分完的序列是无序的。比如:1 1 2和2 1 1是算同一种方案。题目要你计算方案数有多少中。 1. 暴力解法 既让要拆分成若干个整数和,那么最容易想到的就是,我把数一开始都拆分成n个1相加,然后减少1的个数。比如输入4,4时,一开始拆分成1,1,1,1,然后还可以拆分成1,1,2。接下去以此类推,每次用较小的数合成一个较大的数。但很显然,这样的做法复杂度是很大的。以下是暴力解法的代码。 #include int n,cnt; void DFS(int sum, int temp, int k) { if (sum == n) cnt++; if (sum cnt = 0; DFS(0, 1, k); printf("%d\n", cnt); } return 0; }但是这么只能过第一个测试点,其他的地方都超时了。 2. 动态规划 既然暴力的方法行不通,那么我们就该换种思路了。实在没有思路的时候我们可以尝试手动计算出n,k都较小时的拆分方案数。结果我们不难发现以下几条规律。 当n==1时,无论k为何值,都只有一种拆分方案。即{1}。 当k==1时,无论n为何值,都只有一种拆分方案。即{1,1,……,1,1}。因为拆分的最大数不能超过k,所以只能拆成1。 当n==k时,根据拆分出来的数是否包含n,可以分成两种情况。 拆分出来的整数包含n,那就只有一种情况,即{n}。拆分出来的整数不包含n,那么这些拆分出来的数中,一定比n小,即n的所有(n-1)拆分。因此dp[n][k]=1+dp[n][k-1];当nk时,根据拆分出来的整数中是否包含k,可以分为两种情况: 拆分出来的整数中包含k,即{k,{a1,a2,……,ai}),其中{a1,a2,……,ai}的和为n-k,可能再次出现k,因此是(n-k)的k拆分。因此这种情况的拆分数是dp[n-k][k]。拆分出来的整数中不包含k的情况,则拆分出来的整数中所有值都比k小,即n的(k-1)划分。拆分数为dp[n][k-1]。所以dp[n][k]=dp[n-k][k]+dp[n][k-1]。 以下是dp写法的参考代码。 #include using namespace std; int main() { int n, k; while (~scanf("%d,%d", &n, &k)) { int dp[200][200]; int i, j; for (i = 1; i if (j == 1 || i == 1) dp[i][j] = 1; else if (j == i) { dp[i][j] = dp[i][j - 1] + 1; } else if (i dp[i][j] = dp[i][j - 1] + dp[i - j][j]; } } } printf("%d\n", dp[n][k]); } return 0; } |
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |