经典问题 整数划分(动态规划)
2014-03-20 12:55
211 查看
1.将n划分成若干个不同的正整数的划分问题 (划分数可以相同)
dp[i][j] 表示对i的划分,而且每个划分数不超过j
当i或j等于1时划分数只有1
(1)当i==j 时,{i==j} 这是一种划分,若不包含j,所以此时最大值为j-1,则为dp[i][j-1];
得dp[i][j]=1+dp[i][j-1];
(2)当i<j 时,{x1,x2,-x3},其中x2>i,因为划分数都为正整数,所以不成立,所以此时相当于对i进行最大值不超过i的划分即dp[i][i]
得dp[i][j]=dp[i][i];
(3)当i>j 时,若划分数为{j,x1,x2,x3.....} 此时划分数中必包含j,有因为每个数可以重复,所以x1,x2,x3.....中可能还含有j,此时相当于对i-j进行j的划分
得dp[i][j]=dp[i-j][j];
2.将n划分为若干个个不同的正整数 注意:划分数不同
这种情况跟第一种情况相同,不过要注意当i>j时两者会有区别,因为是划分为若干个不同的正整数,所以当划分数中含有j时,就不能从剩下的i-j的数中划分出j来,最大到j-1
于是得dp[i][j]=dp[i-j][j-1]+dp[i][j-1]
3.将n划分为最大值不超过k的划分数
设dp[i][j]表示最大值不超过j的划分数
(1)当i<j 时,划分数的最大值为j,而i<j,又不能包含负数,所以此时dp[i][j]=dp[i][i]
(2)当i==j 时,{i==j} 划分数为1,当不包含j,划分数为dp[i][j-1] 得dp[i][j]=dp[i][j-1]+1;
(3)当i>j 时,若划分数中含有j,得dp[i-j][j] 若划分数不含j得dp[i][j-1]
4.将n划分为k个正整数之和的划分数
设dp[i][j]表示将i划分为j个正整数之和
i==1 或者j==1 时dp值为1
(1)当i==j 时,只有{1,1,1,.....}和为i,只有这一种情况
(2)当i<j 时,因为最多能划分成i个数,而j>i,所以这种情况下为0
(3)当i>j 时,若每个划分数大于等于2,这种情况相当于先划分j个1,然后再将剩余的i-j划分j个数即dp[i-j][j];
若至少含有一个1,则相当于将i-1,划分为j-1个数
5.将n划分为若干奇数的和
dp[i][j] 表示划分最大奇数不超过j的个数
dp[i][j]=dp[i-n(j)][j]+dp[i][j-1] n(j) 表示不超过j的最大奇数
初始化:dp[i][1]=1 ,当i为奇数时dp[0][i]=1;
j为偶数时候dp[i][j]=dp[i][j-1]
dp[i][j] 表示对i的划分,而且每个划分数不超过j
当i或j等于1时划分数只有1
(1)当i==j 时,{i==j} 这是一种划分,若不包含j,所以此时最大值为j-1,则为dp[i][j-1];
得dp[i][j]=1+dp[i][j-1];
(2)当i<j 时,{x1,x2,-x3},其中x2>i,因为划分数都为正整数,所以不成立,所以此时相当于对i进行最大值不超过i的划分即dp[i][i]
得dp[i][j]=dp[i][i];
(3)当i>j 时,若划分数为{j,x1,x2,x3.....} 此时划分数中必包含j,有因为每个数可以重复,所以x1,x2,x3.....中可能还含有j,此时相当于对i-j进行j的划分
得dp[i][j]=dp[i-j][j];
for(int i=1;i<MAX;i++){//初始化 方法一 dp1[i][1]=dp1[1][i]=1; } for(int i=1;i<MAX;i++){ for(int j=1;j<MAX;j++){ if(i<j){ dp1[i][j]=dp1[i][i]; } else if(i==j){ dp1[i][j]=dp1[i][j-1]+1; } else dp1[i][j]=dp1[i-j][j]+dp1[i][j-1]; } }
dp1[0][0]=1;//初始化方法二 for(int i=0;i<MAX;i++){ for(int j=1;j<MAX;j++){ if(i>=j){ //划分数中含有j,与不含j两种情况 dp1[i][j]=dp1[i-j][j]+dp1[i][j-1]; } else dp1[i][j]=dp1[i][i]; } }
2.将n划分为若干个个不同的正整数 注意:划分数不同
这种情况跟第一种情况相同,不过要注意当i>j时两者会有区别,因为是划分为若干个不同的正整数,所以当划分数中含有j时,就不能从剩下的i-j的数中划分出j来,最大到j-1
于是得dp[i][j]=dp[i-j][j-1]+dp[i][j-1]
for(int i=1;i<MAX;i++){//初始化方法一 dp[i][1]=dp[1][i]=1; } for(int i=1;i<MAX;i++){ for(int j=1;j<MAX;j++){ if(i<j){ dp[i][j]=dp[i][i]; } else if(i==j){ dp[i][j]=dp[i][j-1]+1; } else dp[i][j]=dp[i][j-1]+dp[i-j][j-1]; } }
dp[0][0]=1;//初始化方法二 for(int i=0;i<MAX;i++){ for(int j=1;j<MAX;j++){ if(i>=j){ //划分数中含有j,与不含j两种情况 dp[i][j]=dp[i-j][j-1]+dp[i][j-1]; } else dp[i][j]=dp[i][i]; } }
3.将n划分为最大值不超过k的划分数
设dp[i][j]表示最大值不超过j的划分数
(1)当i<j 时,划分数的最大值为j,而i<j,又不能包含负数,所以此时dp[i][j]=dp[i][i]
(2)当i==j 时,{i==j} 划分数为1,当不包含j,划分数为dp[i][j-1] 得dp[i][j]=dp[i][j-1]+1;
(3)当i>j 时,若划分数中含有j,得dp[i-j][j] 若划分数不含j得dp[i][j-1]
for(int i=1;i<MAX;i++){ dp[i][1]=dp[1][i]=1; } for(int i=1;i<MAX;i++){ for(int j=1;j<MAX;j++){ if(i<j) dp[i][j]=dp[i][i]; else if(i==j) dp[i][j]=1+dp[i][j-1]; else dp[i][j]=dp[i][j-1]+dp[i-j][j]; } }
4.将n划分为k个正整数之和的划分数
设dp[i][j]表示将i划分为j个正整数之和
i==1 或者j==1 时dp值为1
(1)当i==j 时,只有{1,1,1,.....}和为i,只有这一种情况
(2)当i<j 时,因为最多能划分成i个数,而j>i,所以这种情况下为0
(3)当i>j 时,若每个划分数大于等于2,这种情况相当于先划分j个1,然后再将剩余的i-j划分j个数即dp[i-j][j];
若至少含有一个1,则相当于将i-1,划分为j-1个数
for(int i=1;i<MAX;i++){ dp[i][1]=dp[1][i]=1; } for(int i=1;i<MAX;i++){ for(int j=1;j<MAX;j++){ if(i==j){ dp[i][j]=1; } else if(i<j){ dp[i][j]=0; } else dp[i][j]=dp[i-1][j-1]+dp[i-j][j]; } }
5.将n划分为若干奇数的和
dp[i][j] 表示划分最大奇数不超过j的个数
dp[i][j]=dp[i-n(j)][j]+dp[i][j-1] n(j) 表示不超过j的最大奇数
初始化:dp[i][1]=1 ,当i为奇数时dp[0][i]=1;
j为偶数时候dp[i][j]=dp[i][j-1]
for(int i=0;i<MAX;i++){ dp4[i][1]=1; if(i&1){ dp4[0][i]=1; } } for(int i=1;i<MAX;i++){ for(int j=1;j<MAX;j++){ if(j&1){ if(j<=i){ dp4[i][j]=dp4[i-j][j]+dp4[i][j-1]; } else dp4[i][j]=dp4[i][i]; } else dp4[i][j]=dp4[i][j-1]; } }
相关文章推荐
- 动态规划-整数划分问题(2)
- 整数划分 --- 一个老生长谈的问题 动态规划
- 整数划分问题解法2-动态规划
- hoj 整数划分问题 经典dp
- OJ 7215 简单的整数划分问题__动态规划
- 整数划分问题(动态规划)
- 整数划分问题---动态规划、递归
- 整数划分问题——动态规划
- 整数划分问题解法2-动态规划
- 动态规划解决整数划分的问题
- NYOJ 651 Cut the rope(DP, 经典的整数划分问题)
- 递归经典整数划分问题
- 整数划分问题---动态规划、递归
- 哈理工OJ 2004 整数划分(经典dp问题)
- 整数划分问题 【经典DP】
- 整数划分问题(动态规划)
- 经典问题一.(插入乘号的整数划分)整数划分(四) nyoj 746
- OpenJudge简单的整数划分问题两种方法(DFS)(动态规划0ms),全局题号7215,已AC
- OJ演练--整数划分(经典DP问题)
- OJ 7219 复杂的整数划分问题__动态规划