POJ1664:放苹果(搜索)

放苹果
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 21860   Accepted: 13944

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

Source

MYCode:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int dfs(int n,int m)
{
    if(m==1)
    return 1;
    if(n==0)
    return 1;
    if(n<m)
    return dfs(n,n);
    return dfs(n,m-1)+dfs(n-m,m);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        int ans=dfs(n,m);
        printf("%d\n",ans);
    }
}
//
解题思路:(source:<<programing guide and online practice>>)
所有不同的摆放方法可以分为两类:至少有一个盘子空着和所有盘子都不空。我们
可以分别计算这两类摆放方法的数目,然后把它们加起来。对于至少空着一个盘子的情
况,则N 个盘子摆放M 个苹果的摆放方法数目与N-1 个盘子摆放M 个苹果的摆放方法
数目相同。对于所有盘子都不空的情况,则N 个盘子摆放M 个苹果的摆放方法数目等
于N 个盘子摆放M-N 个苹果的摆放方法数目。我们可以据此来用递归的方法求解这个
问题。
设f(m, n) 为m 个苹果,n 个盘子的放法数目,则先对n 作讨论,如果n>m,必定
有n-m 个盘子永远空着,去掉它们对摆放苹果方法数目不产生影响;即if(n>m) f(m,n) =
f(m,m)。当n <= m 时,不同的放法可以分成两类:即有至少一个盘子空着或者所有盘子
都有苹果,前一种情况相当于f(m , n) = f(m , n-1); 后一种情况可以从每个盘子中拿掉
一个苹果,不影响不同放法的数目,即f(m , n) = f(m-n , n)。总的放苹果的放法数目等于
两者的和,即 f(m,n) =f(m,n-1)+f(m-n,n)
//
这道题的问题在于如何相同的方案不能够重复计数.
如果从前往后搜索,无法排除相同方案的重复计数.
上面的做法则是从全局考虑的,至少有一个盘子空或者是全部盘子都不空.思路很巧妙.
如果只有一个盘子,那么方案数为1.
如果一个苹果都没有,那么方案数为1.
posted @ 2012-11-24 17:30  java程序员-c  阅读(232)  评论(0编辑  收藏  举报