zoukankan      html  css  js  c++  java
  • 数的划分终极版--背包法解决各类数的划分

    例:NOI 7219:复杂的整数划分问题

    总时间限制: 
    200ms
     
    内存限制: 
    65536kB
    描述

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

    输入
    标准的输入包含若干组测试数据。每组测试数据是一行输入数据,包括两个整数N 和 K。 
    (0 < N <= 50, 0 < K <= N)
    输出
    对于每组测试数据,输出以下三行数据:
    第一行: N划分成K个正整数之和的划分数目
    第二行: N划分成若干个不同正整数之和的划分数目
    第三行: N划分成若干个奇正整数之和的划分数目
    样例输入
    5 2
    样例输出
    2
    3
    3
    提示
    第一行: 4+1, 3+2,
    第二行: 5,4+1,3+2
    第三行: 5,1+1+3, 1+1+1+1+1+1
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    const int N=51;
    int f1[N][N],f2[N],f3[N];
    int sum[N],jsum[N];
    int n,k;
    void init()
    {
        f2[0]=f3[0]=1;
        for(int i=1;i<N;++i)
        sum[i]=i;
        int t=0;
        for(int i=1;i<N;i+=2)
        jsum[++t]=i;
        for(int i=1;i<N;++i)
          for(int j=1;j<=i;++j)
          {
              if(j==1)
              f1[i][j]=1;
              else if(i>=j)
              f1[i][j]=f1[i-1][j-1]+f1[i-j][j];/*N划分成K个正整数之和的划分数目*/
          
          }
        for(int i=1;i<N;++i)
          for(int j=N-1;j>=sum[i];--j)
          f2[j]+=f2[j-sum[i]];/* N划分成若干个不同正整数之和的划分数目*/
        for(int i=1;i<=t;++i)/*注意这里是t,而不是N*/
          for(int j=jsum[i];j<N;++j)
          f3[j]+=f3[j-jsum[i]];/*N划分成若干个奇正整数之和的划分数目*/
    }
    int main()
    {
        init();
        while(scanf("%d%d",&n,&k)==2)
        {
            if(n==0)printf("0
    0
    0
    ");
            else 
            printf("%d
    %d
    %d
    ",f1[n][k],f2[n],f3[n]);
        }
        return 0;
    }
    View Code

    第一行: N划分成K个正整数之和的划分数目
    第二行: N划分成若干个不同正整数之和的划分数目
    第三行: N划分成若干个奇正整数之和的划分数目

    解析:对于"N划分成K个正整数之和的划分数目",无法使用背包法,还是用传统的f[n][m]=f[n-1][m-1]+f[n-m][m];

    而对于N划分成若干个不同正整数之和的划分数目,可以生成一个正整数数列作为物品,跑01背包,题目就是恰好放满背包的方案数目,注意f[0]=1就可以了。

    对于“N划分成若干个奇正整数之和的划分数目”,就生成一个正奇数数列作为物品,跑完全背包还是01背包取决于,是否有“不同的数”。

    而对于“将n划分成最大数不超过k的划分数。”,就生成一个1--k的数列,跑01背包或者完全背包就可以了。

  • 相关阅读:
    ini_set /ini_get函数功能-----PHP
    【转】那个什么都懂的家伙
    word 2007为不同页插入不同页眉页脚
    August 26th 2017 Week 34th Saturday
    【2017-11-08】Linux与openCV:opencv版本查看及库文件位置等
    August 25th 2017 Week 34th Friday
    August 24th 2017 Week 34th Thursday
    August 23rd 2017 Week 34th Wednesday
    August 22nd 2017 Week 34th Tuesday
    August 21st 2017 Week 34th Monday
  • 原文地址:https://www.cnblogs.com/c1299401227/p/5358590.html
Copyright © 2011-2022 走看看