【整數劃分dp(總結)】nyoj 571 整數劃分
阿新 • • 發佈:2019-02-17
整數劃分(一)(二)(三)(四)(五)後接分析
/* 整數劃分 (一)將n劃分成若干不同整數之和的劃分數 (二)將n劃分成若干正整數之和的劃分數 (三)將n劃分成k個正整數之和的劃分數 (四)將n劃分成最大數不超過k的劃分數 (五)將n劃分成若干個 奇正整數之和的劃分數 */ #include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<vector> #include<queue> #include<set> #include<map> #include<algorithm> #include<sstream> #define eps 1e-9 #define pi acos(-1) #define INF 0x7fffffff #define inf -INF #define MM 12900 #define N 50 using namespace std; typedef long long ll; const int _max = N + 10; int dp[_max][_max],n,k,out[6]; int main(){ #ifndef ONLINE_JUDGE freopen("input.txt","r",stdin); #endif // ONLINE_JUDGE while(scanf("%d%d",&n,&k)==2){ /*****************整數劃分(二)******************/ memset(dp,0,sizeof(dp)); dp[0][0] = 1; for(int i = 0; i <= n; ++ i) for(int j = 1; j <= n; ++ j){ if(j>i)dp[i][j]=dp[i][i]; else dp[i][j] = dp[i-j][j] + dp[i][j-1]; } out[1] = dp[n][n]; /*****************整數劃分(四)******************/ out[3] = dp[n][k]; /*****************整數劃分(三)******************/ memset(dp,0,sizeof(dp)); dp[0][0] = 1; for(int i = 1; i <= N; ++ i) for(int j = 1; j <= i; ++ j){ dp[i][j] = dp[i-1][j-1]+dp[i-j][j]; } out[2] = dp[n][k]; /*****************整數劃分(五)******************/ memset(dp,0,sizeof(dp)); dp[0][0] = 1; for(int i = 0; i <= n; ++ i) for(int j = 1; j <= n; ++ j){ if(j&1){ if(j>i)dp[i][j] = dp[i][i]; else dp[i][j] = dp[i-j][j]+dp[i][j-1]; } else dp[i][j] = dp[i][j-1]; } out[4] = dp[n][n]; /*****************整數劃分(一)******************/ memset(dp,0,sizeof(dp)); dp[0][0] = 1; for(int i = 0; i <= n; ++ i) for(int j = 1; j <= n; ++ j){ if(j>i)dp[i][j]=dp[i][i]; else dp[i][j] = dp[i-j][j-1] + dp[i][j-1]; } out[5] = dp[n][n]; /*****************輸出******************/ for(int i = 1; i<= 5; ++ i) printf("%d\n",out[i]); printf("\n"); } return 0; } /* /*****(一)將n劃分成若干不同整數之和的劃分數************ dp[i][j]表示將整數i劃分成不超過j的劃分數,分含不含j兩種情況 dp[0][0] = 1 dp[i][j] = dp[i-j][j-1] + dp[i][j-1];(j<=i) = dp[i][i] (j >i) =>ans = dp[n][n] /*****(二)將n劃分成若干正整數之和的劃分數************* dp[i][j]表示將整數i劃分成不超過j的劃分數,分含不含j兩種情況 與(一)區別,j可重複 dp[0][0] = 1 dp[i][j] = dp[i-j][j] + dp[i][j-1];(j<=i) = dp[i][i] (j >i) =>ans = dp[n][n] /*****(三)將n劃分成k個正整數之和的劃分數************* dp[i][j]表示將整數i劃分成j個正整數的劃分數,考慮j組數中含不含1 dp[0][0] = 1 dp[i][j] = dp[i-1][j-1] + dp[i-j][j]; 如果不包含1,那麼每組數至少為2,從每堆數中各拿出1還能夠成j堆數dp[i-j][j] =>ans = dp[n][k] /*****(四)將n劃分成最大數不超過k的劃分數************ dp[i][j]表示將整數i劃分成不超過j的劃分數,分含不含j兩種情況 是(二)的特例 dp[0][0] = 1 dp[i][j] = dp[i-j][j] + dp[i][j-1];(j<=i) = dp[i][i] (j >i) =>ans = dp[n][k] /*****(五)將n劃分成若干個 奇正整數之和的劃分數****** dp[i][j]表示將整數i劃分成不超過j的劃分數,分含不含j兩種情況 dp[0][0] = 1; j是奇數,正常判斷 dp[i][j] = dp[i-j][j] + dp[i][j-1];(j<=i) = dp[i][i] (j >i) j是偶數,dp[i][j] = dp[i][j-1]//往下遞推 =>ans = dp[n][n] */