POJ1664(整数划分)

放苹果

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 30894   Accepted: 19504

Description

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

Input

第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含二个整数M和N,以空格分开。1<=M,N<=10。

Output

对输入的每组数据M和N,用一行输出相应的K。

Sample Input

1
7 3

Sample Output

8

最基础的整数划分,求将n拆分成不超过m个数之和的方法数
递归法:
       根据n和m的关系,考虑以下几种情况:
       (1)当n=1时,不论m的值为多少(m>0),只有一种划分即{1};
        (2) 当m=1时,不论n的值为多少,只有一种划分即n个1,{1,1,1,...,1};
        (3) 当n=m时,根据划分中是否包含n,可以分为两种情况:
              (a). 划分中包含n的情况,只有一个即{n};
              (b). 划分中不包含n的情况,这时划分中最大的数字也一定比n小,即n的所有(n-1)划分。
              因此 f(n,n) =1 + f(n,n-1);
        (4) 当n<m时,由于划分中不可能出现负数,因此就相当于f(n,n);
        (5) 但n>m时,根据划分中是否包含最大值m,可以分为两种情况:
               (a). 划分中包含m的情况,即{m, {x1,x2,...xi}}, 其中{x1,x2,... xi} 的和为n-m,因此这种情况下
                 为f(n-m,m)
               (b). 划分中不包含m的情况,则划分中所有值都比m小,即n的(m-1)划分,个数为f(n,m-1);
              因此 f(n, m) = f(n-m, m)+f(n,m-1);
      综上所述:
             f(n, m)=   1;                (n=1 or m=1)
                        f(n, n);                        (n<m)
                        1+ f(n, m-1);                (n=m)
                        f(n-m,m)+f(n,m-1);      (n>m)
 1 //2016.9.1
 2 #include <iostream>
 3 #include <cstdio>
 4 #define N 15
 5 
 6 using namespace std;
 7 
 8 int f(int n, int m)
 9 {
10     if(n==1 || m==1)return 1;
11     else if(n < m)return f(n, n);
12     else if(n == m)return (1+f(n, n-1));
13     else return f(n-m, m)+f(n, m-1);
14 }
15 
16 int main()
17 {
18     int T, n, m;
19     cin>>T;
20     while(T--)
21     {
22         scanf("%d%d", &n, &m);
23         int ans = f(n, m);
24         cout<<ans<<endl;
25     }
26 
27     return 0;
28 }
原文地址:https://www.cnblogs.com/Penn000/p/5830532.html