【DP_動態規劃】整數劃分
題目連結:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=90
整數劃分
時間限制:3000 ms | 記憶體限制:65535 KB
難度:3
輸入
第一行是測試資料的數目M(1<=M<=10)。以下每行均包含一個整數n(1<=n<=10)。
輸出
輸出每組測試資料有多少種分法。
描述
將正整數n表示成一系列正整數之和:n=n1+n2+…+nk,
其中n1≥n2≥…≥nk≥1,k≥1。
正整數n的這種表示稱為正整數n的劃分。求正整數n的不
同劃分個數。
例如正整數6有如下11種不同的劃分:
6;
5+1;
4+2,4+1+1;
3+3,3+2+1,3+1+1+1;
2+2+2,2+2+1+1,2+1+1+1+1;
1+1+1+1+1+1。
#include <iostream> using namespace std; int cnt,n; int memo[11][11]; void init(); int dp(int n, int m); int main() { cin>>cnt; while(cnt--) { cin>>n; init(); cout<<dp(n, n)<<endl; } return 0; } void init() { for(int i=0; i<=n; i++) { for(int j=0; j<=n; j++) { memo[i][j]=0; } } } int dp(int n, int m) { if(memo[n][m]) { return memo[n][m]; } else if(n==1||m==1) { memo[n][m]=1; return memo[n][m]; } else if(m>n) { memo[n][m]=dp(n, n); return memo[n][m]; } else if(m==n) { memo[n][m]=1+dp(n, m-1); return memo[n][m]; } else { memo[n][m]=dp(n-m, m)+dp(n, m-1); return memo[n][m]; } }
【2018/11/8後記】
1.本題用了動態規劃法+備忘錄法,遞迴公式如下:
其中q(n,m)代表:要劃分的整數為n,最大的加數<=m
如:q(3,2)代表:將3進行劃分,最大的加數不能超過2,因此只有2+1,1+1+1這兩種分法,因此q(3,2)=2
n和m的值有以下幾種情況:
第一種情況:當n==1時,即要劃分的整數為1,自然只有一種分法;當m==1時,n只能被劃分成n個1相加,也只有一種分法
第二種情況:當n<m時,即要劃分的整數為n,加數<=m。又因為加數<=n&&n<m,所以q(n,m)=q(n,n)
第三種情況:當n=m時,我們可以將其分成兩種子情況:
①子情況:讓最大的加數=m,那麼分法只有1種:n=m
②子情況:讓最大的加數<=m-1,那麼問題轉換成q(n,m-1),因為m=n,所以q(n,m-1)=q(n,n-1)
所以,第三種情況的分法q(n,m)=1+q(n,n-1)
第四種情況:當n>m時,我們可以將其分成兩種子情況:
①子情況:讓最大的加數=m,那麼問題轉換成q(n-m,m)
②子情況:讓最大的加數<m,那麼問題轉換成q(n,m-1)
所以,第四種情況的分法q(n,m)=q(n-m,m)+q(n,m-1)
詳細講解請轉這篇部落格:https://blog.csdn.net/qq_41333482/article/details/82823742
2、這道題跟裝盤子那道差不多了 ,都是要分子情況