POJ 1664 放置苹果

来源:互联网 发布:车辆保养记录查询软件 编辑:程序博客网 时间:2024/05/16 11:42

Name: 放置苹果
P_ID: POJ1664(BNUOJ1783)
题目描述:
把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

分析:
这个题应该很明显是要用递归做的,关键就是怎么递归。
这个题我自己是没有想出怎么递归的,这里我放一个递归函数:
f(m, n) = f(m-n, n) + f(m, n-1);
其中,
f(m,n)是指把m个苹果放置到n个盘子中的方法数,
f(m-n, n)是指把m个苹果放置到n各盘子中,且满足 每个盘子都有苹果。具体做法就是先每个盘子放一个再说。也就是转化为m-n个苹果放置到n各盘子中的方法数。
f(m, n-1)是指把m个苹果放置到n个盘子中,且存在一个空盘子的情况。
注:之所以等于两者相加,是因为 等号右边第一项其实包含了所有没有空盘子的情况,第二项包含了所有存在空盘子的情况。
因为如果所有盘子都有且只有一个苹果,一次递归就解决了,如果多于一个,会在之后的递归中体现,而不同盘子都有苹果但不一定数量相同的情况会在执行了i次递归后转化为存在空盘子的情况。而相应的,存在空盘子的情况已经移交给等号右边第二项来处理,且随着递归次数增加,n不断减小,减小的那部分,全都是空盘子,所以所有包含空盘子可能性的情况都包含在内了。
这里会导致几个问题:
1. 会出现m-n小于等于0的情况,这种情况直接返回1就好。
2. 会出现n小于等于0的情况,同上。

参考代码:

/** * name: Apple * P_ID: BNUOJ 1783 * date: 2016-04-06 */#include <cstdio>#include <cstring>using namespace std;int a, b, ans;int f(int x, int n){    if(x<=1 || n<=1) return 1;    if(x<n) return f(x, x);    return (f(x-n, n) + f(x, n-1));}int main(){    int T;    scanf("%d", &T);    while(T--)    {        ans = 0;        scanf("%d%d", &a, &b);        ans = f(a, b);        printf("%d\n", ans);    }    return 0;}
0 0
原创粉丝点击