【动态规划】划分整数
2018-03-28 20:00
274 查看
大致思路(关键):
dp[i][j] 代表能把i划分成不多于j个正整数相加。
当i<j:显然最多只能划分成i个1相加,或者划分成小于i个份数,即划分成小于等于i份。所以=dp[i][i]
当i>j:
①如果要刚好分为j份正整数,则=dp[i-j][j] 。 (这步比较难想,但是我通过”逆向思考“和“坐位子思路”想懂了:
先看dp[i-j][j]嘛,可以把i-j这个数分为j或少于j个正整数相加,想象有j个位子,当分为少于j个正整数相加时(比如说j-2个正整数相加),我们可以把那剩下的两个位子以0占位。那么你想想,对每一种情况,现在把j个位子上每个数都+1(使i-j->i),是不是就保证了每个位子上都是正整数。这样就符合了dp[i][j]让它j个位子上都是正整数,从而满足了刚好把i分为j份正整数相加。
②如果要分为少于j份正整数相加,那么就是要<j即<=j-1,所以这不就是dp[i][j-1]吗?(抓住j的含义——小于等于j份
所以=dp[i-j][j]+dp[i][j-1]
当i==j:
很明显你要把i分为j份或者小于j份:分成j份那就是分成j个1即i个1,分成<j份那就分成<=j-1份。所以=1+dp[i][j-1]
临界条件:dp[1][1]=1;
AC代码:#include<iostream>
#include<bits/stdc++.h>
using namespace std;
long long dp[301][301]; //dp
[k]表示把n分解成不多于k个正整数相加
int main()
{
memset(dp,0,sizeof(dp));
int n,k;
cin>>n>>k;
dp[1][1]=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=k;j++)
{
if(i==1 && j==1 )
continue;
if(i==j)
{
dp[i][j]=1+dp[i][j-1];
}
if(i>j)
{
dp[i][j]=dp[i-j][j]+dp[i][j-1];
}
if(i<j)
{
dp[i][j]=dp[i][i];
}
}
}
cout<<dp
[k];
return 0;
} 感觉思考动态规划其实不要太陷入数字里去,而是在把dp数组的下标和其值代表的含义记清楚之后,去联系实际递推各种情况之间的联系。也就是重要在找状态转移方程上。
相关文章推荐
- nyoj-90 整数划分 (动态规划)
- 整数划分问题解法2-动态规划
- 整数划分问题---动态规划、递归
- 整数划分 (递归、分治、动态规划)
- 动态规划-整数划分问题(2)
- 动态规划-各种整数划分
- HDU 1028 Ignatius and the Princess III(母函数 或者 整数划分的DP动态规划)
- 整数划分 用递归,动态规划,母函数法实现
- 整数划分-划分数(DP动态规划)
- 整数划分总结(动态规划)
- 整数划分 --- 一个老生长谈的问题 动态规划
- 动态规划解决整数划分的问题
- 动态规划解整数划分
- OpenJudge简单的整数划分问题两种方法(DFS)(动态规划0ms),全局题号7215,已AC
- 经典问题 整数划分(动态规划)
- 整数划分 --- 一个老生长谈的问题 动态规划
- 【动态规划/背包】整数划分的5种情况
- 整数划分问题(动态规划)
- OJ 7215 简单的整数划分问题__动态规划
- 整数划分 --- 一个老生长谈的问题 动态规划