• 数的划分


    描述

    将整数n分成k份,且每份不能为空,任意两份不能相同(不考虑顺序)。

    例如:n=7,k=3,下面三种分法被认为是相同的。

    1,1,5; 1,5,1; 5,1,1;

    问有多少种不同的分法。 输出:一个整数,即不同的分法。

    输入

    两个整数n,k (6 < n <= 200,2 <= k <= 6),中间用单个空格隔开。

    输出

    一个整数,即不同的分法。

    样例输入

    7 3

    样例输出

    4

    提示

    四种分法为:1,1,5;1,2,4;1,3,3;2,2,3。

    【题目 http://noi.openjudge.cn/ch0206/8787/】

    分析

    显然是个动规

    方程:f[i,j]=f[i-1,j-1]+f[i,j-i]

    这题可以看成把N个苹果放在K个盘子里,每个盘子都不能为空(即每个盘子里至少有一个苹果),求方案数

    设f[i,j]表示j个苹果放在i个盘子的方案数

    初始化很好理解,不管把几个苹果放在一个盘子里都只有一种放法,所以f[1,i]:=1;

    好啦,初始化解释完就不管了

    现在来看f[i,j]=f[i-1,j-1]+f[i,j-i];

    假设现在盘子全为空,苹果都不在盘子里,我们开始放苹果吧!

    (1):先在一个盘子里放一个苹果,就剩下j-1个苹果放在i-1个盘子里,有f[i-1,j-1]种放法
    (2):再把盘子里的苹果全都拿出来(让盘子全为空),然后再开始放。 这次先在一个盘子里放两个苹果,就剩下j-2个苹果放在i-1个盘子里,有#种放法(先不管‘#’)是多少

    (3):再把盘子里的苹果全都拿出来(让盘子全为空),然后再开始放。 这次先在一个盘子里放三个苹果,就剩下j-3个苹果放在i-1个盘子里,有#种放法(不管‘#’)是多少

    ……

    以此类推,直到在一个盘子里放j-i+1个苹果,然后把这些方案数加起来,存在f[i,j]。

    先在一个盘子里放一个苹果的方案数已经知道了,就先让f[i,j]=f[i-1,j-1]+%&#@,先不管%&#@是什么,回顾一下前面,从2开始就不好求了,因为你不知道当你先在一个盘子里放M(M>1)个苹果后求出来的方案有没有和前面重复。

    那就换种思路来求除了(1)以外的方案数吧

    看看题目的约束条件,即每个盘子里至少有一个苹果,为了满足条件,就让每个盘子里都有一个苹果,然后剩下j-i个苹果放在i个盘子里(有个盘子只有一个苹果的情况在(1)已经考虑过了,所以现在每个盘子至少要有两个苹果),而j-i个苹果放在i个盘子里的方案数已经算出来了(f[i,j-i]),每个方案都保证往当前的每个盘子中放至少一个苹果,当前每个盘子里已经都有一个苹果,所以这样一来每个盘子至少有两个苹果,(2)就包括在里面了。以此类推,(3),(4)……也都包括在(如果可能)f[i,j-i]里。所以加上f[i,j-i]就好了。

    pascal代码

    program sdfg;
    var
      n,k,i,j:longint;
      f:array[0..200,0..200] of longint;
    begin
      readln(n,k);
      for i:=1 to n do
        f[i,1]:=1;
      for i:=1 to n do
        for j:=2 to i do
          f[i,j]:=f[i-1,j-1]+f[i-j,j];
      writeln(f[n,k]);
    end.

    c++代码

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <string>
    #include <cstdio>
    #include <queue>
    #include <ctime>
    #include <cmath>
    int f[210][210];
    int main()
    {
    //    freopen("numf.in","r",stdin);
    //    freopen("numf.out","w",stdout);
        int n,k,i,j;
        scanf("%d%d",&n,&k);
        for (i=1;i<=n;i++)
          f[i][1]=1;
        for (i=1;i<=n;i++)
          for (j=2;j<=i;j++)  
            f[i][j]=f[i-1][j-1]+f[i-j][j];
        printf("%d",f[n][k]);
        return 0;    
    }

    这是我第一次写题解,写的不好多多包涵

    【这也是我的第一篇博客】

  • 相关阅读:
    (转)基于MapWinGis开发探索(一)
    ArcGIS Server REST API开发相关新词汇
    自写地图全图功能
    向远程目录写数据
    GetUpperBound方法
    监控安装教程
    办公室局域网打印机共享设置
    电脑Bois中usb模式启动热键
    SQL SERVER 2005无法远程连接
    用网线直接把打印机连入网络的问题
  • 原文地址:https://www.cnblogs.com/rabbit1103/p/7778066.html
Copyright © 2020-2023  润新知