0827 OpenJ#7219 复杂的整数划分问题

来源:互联网 发布:航信开票软件 编辑:程序博客网 时间:2024/06/11 07:37
摘要
-背包问题的变形 使用01背包 完全背包解决
原题目摘要
-复杂的整数划分问题

-
描述

将正整数n表示成一系列正整数之和,n=n1+n2+…+nk,其中n1>=n2>=…>=nk>=1k>=1
正整数n的这种表示称为正整数n的划分。

输入
标准的输入包含若干组测试数据。每组测试数据是一行输入数据,包括两个整数N 和 K。
(0 < N <= 50, 0 < K <= N)
输出
对于每组测试数据,输出以下三行数据:
第一行: N划分成K个正整数之和的划分数目
第二行: N划分成若干个不同正整数之和的划分数目
第三行: N划分成若干个奇正整数之和的划分数目
样例输入
5 2
样例输出
233
提示
第一行: 4+1, 3+2,
第二行: 5,4+1,3+2
第三行: 5,1+1+3, 1+1+1+1+1+1


题目理解
- 将第一个看做 选k个的满足一定数量的背包,第二个看成,N个中选择满足数量的01背包,第三个与第一个类似
注意
-第二个说的是不同的所以所有的数只能出现一次 四三个要求的是奇数 遇到偶数要转一下  可惜我目前觉得这样好做一点__  不过应该有其他的办法
日期
-2017 0827
附加
-
代码
-
#include <algorithm>#include <iostream>#include <memory>#include <cstdio>using namespace std;#define MAX 55int dp1[MAX][MAX][MAX];//h,w,m,1-h/0-wint dp2[MAX][MAX];int dp3[MAX][MAX];int ans1=0;int _dp3(int n,int m){//不超过n k个m的划分    if(n<1) return 0;    if(m==0) return 1;    if(n%2==0) n--;    if(dp3[n][m]!=-1) return dp3[n][m];    int ans = 0;    if(m>=n)ans+=_dp3(n,m-n);    ans+=_dp3(n-1,m);    return dp3[n][m]=ans;}int _dp2(int n,int m){//n不超过m的 不同划分 01    if(n==0) return 1;    if(n>0&&m==0)return 0;    if(dp2[n][m]!=-1) return dp2[n][m];    int ans = 0;    if(n>=m) ans+=_dp2(n-m,m-1);    ans+=_dp2(n,m-1);    return dp2[n][m]=ans;}int _dp1(int n,int m,int k){//不超过n k个m的划分    if(n<1) return 0;    if(m==0&&k==0) return 1;    if(k==0||m==0) return 0;if(dp1[n][m][k]!=-1) return dp1[n][m][k];    int ans = 0;    if(m>=n)ans+=_dp1(n,m-n,k-1);    ans+=_dp1(n-1,m,k);    return dp1[n][m][k]=ans;}int n,k;void solve(){        cout<<_dp1(n,n,k)<<endl;    cout<<_dp2(n,n)<<endl;    cout<<_dp3(n,n)<<endl;}int main(){    memset(dp1,-1,sizeof(dp1));    memset(dp2,-1,sizeof(dp2));    memset(dp3,-1,sizeof(dp3));    while(~scanf("%d%d",&n,&k))solve();    return 0;}