您的位置:首页 > 其它

经典问题 整数划分(动态规划)

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];

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];
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  动态规划