1. 程式人生 > >整數劃分-劃分數(DP動態規劃)

整數劃分-劃分數(DP動態規劃)

給你一個正整數n,讓你計算出n的m劃分有幾種方法。

思路定義dp[i][j]為i的j劃分,即將i劃分為j個數字之和的方案數。

1:當j<=i時,此時,劃分個數不超過i,此時是正常的劃分。

     劃分的結果一定只有兩種型別:一種是j個數字,都大於0。另一種是有0,即不夠劃分j個,用0來湊的。

     j個數字中存在0的,其實就是前一個劃分j-1的方案數,補0就行,即dp[i][j-1]。

     j個數字均大於0的,此時也能呼叫之前的解求出,已經當前j個數字均大於0,我們將每個數字都減去1,此時在保證j個數字結構不變,且非負的情況下,dp[i-j][j]就是當前dp[i][j]不為0的方案數。

2:當j>i,此時劃分個數超過i本身,此時j個數字必然存在0,且只有這一種情況,此時直接dp[i][j-1];

 j<=i時:dp[i][j]=dp[i][j-1]+dp[i-j][j]

   j > i時:dp[i][j]=dp[i][j-1]

程式碼:

#include<bits/stdc++.h>
ll dp[550][550],n,m;
int main()
{
    while(~scanf("%lld%lld",&n,&m))
    {
        memset(dp,0,sizeof(dp));
        for(ll i=1;i<=m;i++)dp[0][i]=1;
        for(ll i=1;i<=n;i++)
        {
            for(ll j=1;j<=m;j++)
            {
                if(j<=i)dp[i][j]=dp[i][j-1]+dp[i-j][j];   //此時兩種情況相加
                else dp[i][j]=dp[i][j-1];   //此時只有存在0這一種情況
            }
        }
        printf("%lld\n",dp[n][m]);
    }
    return 0;
}