2011.10.22 poj1664放苹果 解题报告

放苹果
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 18762 Accepted: 11905

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
 
一、做题状况:
想了很久,没有思路,借鉴了别人的思路,然后拿来主义,消化掉后,开始码代码,码代码的过程中注意利用DP的中记忆化的思想,防止计算已经算过的位置。最后提交,直接AC。
二、思路分析:
设f(m,n)为把m个苹果放到n个盘子中的方法数,m>=0,n>=0.
若m和n中任何一个等于0,那么f(m,n) = 1,注意不是等于0,因为相当于就那么一种结果,就是不往盘子里面放(没有苹果),或者,连盘子都没有。
若n=1,显然对于任意的m>=0 有f(m,1) = 1
若m=1,显然对于任意的n>=0 有f(1,n) = 1
接下来讨论m>1 && n>1的情况:
若 m < n 则 f(m,n) = f(m,m)。(f(m,m)怎么算呢? 看m>=n的情况不就知道了吗?)
若 m>=n 则 大体有两种放法:第1种:至少有一个盘子为空,即什么也不放,这部分的方法数为f(m,n-1);
                       第2种:全部盘子都有苹果,那么先从m个苹果中抽取出n个出来,各个盘子分一个,考虑剩下的m-n个苹果放到n个盘子里的放法,这样就成功把f(m,n)降到了f(m-n,n)。
                       所以,m>=n时,有f(m,n) = f(m,n-1) + f(m-n,n);
思路分析完毕。
三、题目类型:递归题目
四、进步
 通过这道题,自己明白了对类似于“往一定数量(n个)的盘子里放一定数量(m个)水果“的常见分析方法。主要涉及到:递归方法 其中包括会用到分类讨论的思想。
  以后遇到这类题,一定要充分思考,不要光想着举例子然后归纳公式,也不要光想着是不是考DP。还是要多分析,学会”降维“,将索引值不断降小,就可以得到解(实际上就是递归的本质)。
五、附源码:
//poj_1664_recursion//result:AC#include<iostream>//#include<cassert>using namespace std;const int MAX_MN = 11;int f[MAX_MN][MAX_MN];int func_f(const int m,int n){	//assert( m>=1 );	//assert( n>=1 );	if( m < 1 || n<1 )	{		int rub = -1;	}	n = m < n ? m :n;	if( f[m][n] != -1 )		return f[m][n];	f[m][n-1] = func_f(m,n-1);	f[m-n][n] = func_f(m-n,n);	return f[m][n-1] + f[m-n][n];}int main(){	int m,n;	int testcase = 0;	cin>>testcase;	while( testcase-- > 0 ){		cin>>m>>n;		for(int i=1; i<=m; ++i)			for(int j=1; j<=n; ++j)				f[i][j] = -1;		f[0][0] = 1;        //注意这个地方f[0][0]应该初始化为1,而不是0,更不是-1.		//n == 1;		for(int i=1; i<=m; ++i)			f[i][1] = 1;		//m == 1;		for(int i=1; i<=n; ++i)			f[1][i] = 1;		f[m][n] = func_f(m,n);		cout<<f[m][n]<<endl;	}	return 0;}

                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值