划分数问题

问题描述:有n个无区别的物品,将它们划分成不超过m组,求出划分方法数 

这是一道经典的不能再经典的题目,当然也有不同的定义方式,下面将从两种方式来分析这个问题

》把n个同样的苹果放在m个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示,5,1,1和1,5,1 是同一种分法

放苹果的问题乍看之下很复杂,盘子是一样的,苹果也是一样的;只要每个盘子里面放的苹果是一样多的,不管顺序如何最终得到的都是同一种分法。其实我们需要把问题简化。就拿这个放苹果的问题而言,我们只需要分两种情况:有空盘子和没空盘子。

1.有空盘子:f(n, m) = f(n, m-1)  //有空盘子很多人会有疑问,这不是只有一个空盘子的情况吗?那2个3个空盘子呢?可以先思考一下

2.没有空盘子:f(n, m) = f(n-m, m)  //没有空盘子,我们可以看成先给每一个盘子放一个苹果,则还剩下n-m个苹果,剩下的问题就是把这n-m个苹果放到m个盘子里的问题了。看到这里你是不是有点明白为什么第一种情况的递推是那样写的,其实本质是一样的,我们可以先看成先看成先让一个盘子空着,还有m-1个盘子,剩下的问题就是吧这n个苹果放到m-1个盘子里的问题。

因此:f(n, m) = f(n, m-1) + f(n-m, m)   ( n>=m) 

上面的表达式并不完整,当m<n时的情况没有考虑,当m<n的时候,f(n, m)就相当于f(n, n)

写到这里主要表达式基本上已经写完了,但是递推一般都要有边界,稍微看一下就能找到,当只有一个盘子时明显只有一种方法,另外没有苹果和只有一个苹果的时候也只有一种放法。即当m=1或者n=0时,f(n, m) = 1      

综上:

f(n, m) = 1  (m=1,n=0)

f(n, m) = f(n, n)   (n<m)

f(n, m) = f(n, m-1) + f(n-m, m)   ( n>=m) 

》将n划分成最大数不超过m的划分数

1.当 n=1,d为1,因为无论m为多少就只有1

2.当 m=1 时,d=1 ,由上例可知,当 n=4 时,d只有 1+1+1+1 这1种

3.当 n=m 时,又分为两种情况:

  • 第一种就是包含m的时候,就只有 m 这一种。
  • 另外一种就是不包含 m ,那么最大数就为 m-1 ,有 d(n,m-1) 种

4.因此当 n=m 时,d(n , n)=1+ d(n,n-1)

5.当n < m 就相当于 d(n,n) 了

6.当 n > m 时,一种是不含m,为d(n,m-1)种,一种是含有m,有d(n-m,m)种

因此d(n,m)=d(n-m,m)+d(n,m-1)

(注意理解d(n-m,m),注意这里的前提是划分包含m,所以将m提出来一个,保证划分中一定会有m,剩下数字划分的和为n-m,而这n-m中可能不会出现m,也可能出现m,但由于我们已经提出了一个m,所以此处不用担心m是否再出现。

第一个数为什么是(n-m),原因是提出一个m后,已经保证了划分中一定出现m,而n-m还没有进行划分,这里忽略提出的m,对剩下的整数n-m进行划分,划分的最大值仍然是m)


前面之所以从不同的角度来分析是为了让你能更好的理解状态之间的递推关系,懂了之后我们就能用动态规划的思想来解决这个问题:

定义题目为n的m划分数

(所有可能的情况都可以看作是把n划分成m份。只是有的是取0的)

那我们可以定义状态:dp[i][j]表示 j 的 i 划分数 (注意,j的i划分表示的意义为 j固定,i可以取到1- i)

状态转移方程:1.j >= i时,dp[i][j] = dp[i-1][j]( j的i-1划分,相当于当前位取0的全部情况 ) + dp[i][j-i](当前位不取0,先把每一个置为1,再将剩下的j-i分下去)

       2.j < i时,dp[i][j] = dp[i-1][j];  当前位只能取0

核心代码:

void solve()
{
    dp[0][0];
    for (int i = 0; i <= m; i++) {
        for (int j = 0; j <= n; j++) {
            if (j>=i)
                dp[i][j] = dp[i-1] + dp[i][j-1];
            else
                dp[i][j] = dp[i-1][j];    
        }
    }
    printf("%d\n", dp[m][n]);
}

参考博客:

https://www.cnblogs.com/zhangjiuding/p/7668938.html

https://blog.csdn.net/qq_33699981/article/details/68978736

https://blog.csdn.net/u012283461/article/details/52761238

猜你喜欢

转载自www.cnblogs.com/wizarderror/p/10463364.html