【整数划分dp(总结)】nyoj 571 整数划分

来源:互联网 发布:js随机函数 编辑:程序博客网 时间:2024/06/06 02:53

http://acm.nyist.net/JudgeOnline/problem.php?pid=571

 整数划分(一)(二)(三)(四)(五)后接分析

/*   整数划分   (一)将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 50using 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]*/




1 0