题目大意:中文
注释代码:
/*
* Problem ID : POJ 1664 放苹果
* Author : Lirx.t.Una
* Language : C
* Run Time : 0 ms
* Run Memory : 172 KB
*/
#include <stdio.h>
//maximum number of apples and plates,苹果和盘子的最大数量(10 + 1)
#define MAXN 11
//memo,备忘录,记录每种情况下(i个苹果j个盘子)的分法数量
//经测试,最大的m[10][10]也只有42,所以使用char可以节省空间
char mm[MAXN][MAXN] = { 0 };
char
par( int m, int n ) {//partition,划分,求m个苹果n个盘子的分法数量
if ( mm[m][n] )//如果已经记录过则直接返回备忘录中的结果
return mm[m][n];
if ( 1 == m || 1 == n ) {//当苹果或盘子至少有一个为1时必定只有一种分法
mm[m][n] = 1;
return 1;//返回常数比返回数组元素节省了从数组中取数的时间
}
//分两种情况讨论
//第一种是苹果数小于盘子数(m < n),就相当于par( m, m )
//第二种是苹果数等于盘子数,即par( m, m ),因此第一种情况可以归结在该情况下
//对于第二种情况,总共有两种情形:
//要么有空盘子要么没有空盘子
//无空盘子的情形就只有每个盘子里刚好都有一个苹果这么1种
//有空盘子的情形可以理解为至少有一个空盘子,那么所有苹果将会在剩下的m - 1个盘子中进行分配
if ( m <= n )
return mm[m][n] = 1 + par( m, m - 1 );
//对于苹果多于盘子的情况也有两种情形
//一种是无空盘,就等价于现在每个盘子中放上一个苹果(从而保证无空盘),
//然后在将剩余的m - n个苹果自由分配到这n个盘子中去
//第二种情况是有空盘,同样,既然有空盘那么就至少会空出一个盘子,
//那么就相当于在剩下的n - 1个盘子中自由分配m个苹果了
return mm[m][n] = par( m, n - 1 ) + par( m - n, n );
}
int
main() {
int nscn;
int m, n;
scanf("%d", &nscn);
while ( nscn-- ) {
scanf("%d%d", &m, &n);
printf("%d\n", par( m, n ));
}
return 0;
}
无注释代码:
#include <stdio.h>
#define MAXN 11
char mm[MAXN][MAXN] = { 0 };
char
par( int m, int n ) {
if ( mm[m][n] )
return mm[m][n];
if ( 1 == m || 1 == n ) {
mm[m][n] = 1;
return 1;
}
if ( m <= n )
return mm[m][n] = 1 + par( m, m - 1 );
return mm[m][n] = par( m, n - 1 ) + par( m - n, n );
}
int
main() {
int nscn;
int m, n;
scanf("%d", &nscn);
while ( nscn-- ) {
scanf("%d%d", &m, &n);
printf("%d\n", par( m, n ));
}
return 0;
}