5. 數的劃分
問題描述
將整數n分成k份,且每份不能爲空,任意兩份不能相同(不考慮順序)。
例如:n=7,k=3,下面三種分法被認爲是相同的。
1,1,5; 1,5,1; 5,1,1;
問有多少種不同的分法。
輸入格式
n,k
輸出格式
一個整數,即不同的分法
樣例輸入
7 3
樣例輸出
4 {四種分法爲:1,1,5;1,2,4;1,3,3;2,2,3;}
解題思路:
dp[n][k]表示把劃分爲k個數的方案種數;
有倆種情況:
不包含1:
則可以先找出k個1放在每一份中,然後把剩下的n-k分成k份即可,即代碼中的 dfs(i-j,j) 部分
包含1:
則先把1拿出來當做單獨的一份,則把n-1劃分成k-1份即可,即代碼中的 dfs(i-1,j-1) 部分
狀態轉移方程爲:
dp[i][j]=dp[i-j][j]+dp[i-1][j-1]; i>j
dp[i][j]=1; i=j || j==1
dp[i][j]=0; i<j
#include<cstdio>
#include<cstdlib>
#include<cstring>
int dfs(int i,int j){
if(i==j||j==1)
return 1;
else if(i<j)
return 0;
else
return dfs(i-j,j)+dfs(i-1,j-1);
}
int main()
{
int n,k;
scanf("%d %d",&n,&k);
int t=dfs(n,k);
printf("%d\n",t);
system("pause");
return 0;
}
一 將n劃分爲若干個整數的劃分數
1.若劃分的若干個整數可以相同
設dp[i][j]爲將i劃分爲不大於j的劃分數
(1) 當i<j時,i不能劃分爲大於i的數,所以dp[i][j]=dp[i][i];
(2) 當i>j時,可以根據劃分中是否含有j分爲兩種情況。
若劃分中含有j,劃分方案數爲dp[i-j][j];
若劃分數中不含j,相當於將i劃分爲不大於j-1的劃分數,爲dp[i][j-1]。
所以當i>j時dp[i][j]=dp[i-j][j]+dp[i][j-1];
(3) 當i=j時,也分爲兩種情況:
若劃分中含有j只有一種情況,
若劃分中不含j相當於將i劃分爲不大於j-1的劃分數。
此時dp[i][j]=1+dp[i][j-1]。
#include<stdio.h>
int A(int i,int j){
if(i==1||j==1) return 1;
else if(i<j)
return A(i,i);
else if(i>j)
return A(i-j,j)+A(i,j-1);
else
return 1+A(i,j-1);
}
int main()
{
int s=A(2,2);
printf("%d\n",s);
return 0;
}
2.若劃分的若干個整數必須不同
設dp[i][j]爲將i劃分爲不超過j的不同整數的劃分數
(1) 當i<j時,i不能劃分爲大於i的數,所以dp[i][j]=dp[i][i];
(2) 當i>j時,可以根據劃分中是否含有j分爲兩種情況。
若劃分中含有j,則其餘的劃分中最大隻能是j-1,方案數爲dp[i-j][j-1];
若劃分中不含j,相當於將i劃分爲不大於j-1的劃分數,爲dp[i][j-1]。
所以當i>j時dp[i][j]=dp[i-j][j-1]+dp[i][j-1];
(3) 當i=j時,兩種情況:
若劃分中含有j只有一種情況;
若劃分中不含j相當於將i劃分爲不大於j-1的劃分數。
此時dp[i][j]=1+dp[i][j-1]。