/***** POJ 1664 放苹果 ********/
/******** written by C_Shit_Hu ************/
/****************************************************************************/
/*
下午简单的用递归解决这道题,但在大神的提示下,说用DFS也可以。。。。
虽然对深度搜索树不甚了解,但在钻研别人的codes的基础上,依然理解了。
把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。
第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含二个整数M和N,以空格分开。1<=M,N<=10。
对输入的每组数据M和N,用一行输出相应的K。
*/
/****************************************************************************/
// 一定要膜拜一下。。。
// 本题是dfs解法。。。
// 深度优先搜索树。。
// 代码如下,注意调用函数!
#include <stdio.h>
#include <string.h>
int t, n, m, s;
int num[11]; // 题目说做多十个盘子,所以。。。
// dfs搜索树算法调用函数
void dfs(int x,int y) // 此处的x代表余下的盘子(深度),y代表剩余的苹果数目(节点)
{
int i = 0;
if(x==m)
{
if(y>=num[m-1])
s++;
} // 如果节点为终端节点。。。就说明找到了一个可能结果
else
{
// 此处的for循环至关重要,首先必须明白,由于是从第一个节点开始搜索,而且为了避免重复
// 其后的的节点上的苹果数目必须要大于等于前面的节点上的苹果数目
// 所以其循环初始条件是从上一个节点开始,循环控制条件是i<=y && y/(m-x) >= i ...
// 此处的x代表的是上一个节点(盘子)里放的苹果数目
for( i=num[x-1]; i<=y&&(y/(m-x)>=i); i++)
{
num[x]=i;
dfs(x+1,y-i); // 如果符合循环条件,则使相应的节点深度赋值,并递归调用
// 递归调用时,是搜索下一个节点深度(盘子),以及剩下的节点(苹果数目)。
}
}
}
int main()
{
scanf("%d",&t);
while(t--)
{
memset(num,0,sizeof(num));
scanf("%d%d",&n,&m);
s=0;
dfs(1,n);
printf("%d\n",s);
}
return 0;
}
/******************************************************/
/******************** 心得体会 **********************/
/*
好吧,,,那个在dfs调用函数里的i的作用。。。理解很重要啊、、、、
表示今天真心学到了。。。
好好学习数和图。。。
搜索算法。。。之基本。
水水更健康!!!
*/
/******************************************************/