题目链接 : putting apples
题目可以理解成求将n拆成k个数(可以是0)的和有多少种方法;比如7 3:
7 = 7 + 0 + 0
= 6 + 1 + 0
= 5 + 2 + 0
= 5 + 1 + 1
= 4 + 3 + 0
= 4 + 2 + 1
= 3 + 3 + 1
= 3+ 2 + 2
共8种.
这里定义一个函数void DFS(int n, int k,int prev);是一个递归函数;其功能是将n拆成2个数a,b的加和的形式,且满足 prev<=a<=b<=n/k;然后b即是下层DFS的n,a则是下层的prev.(以上关系可由任一特例推测出来).
需要注意的是,如果单纯照上述公式编码,最后会导致TLE,对于这种情况一般可以考虑加个标记数组,这里定义flag[i][j][k] 表示prev = i,n = j,k = k时的结果,即可避免TLE的结果;
AC代码
/*
提交两次,一次未加标记数组TLE,第二次AC 0.012s 2572k
内存占用太大,算法不优
*/
#include <stdio.h>
#define MAXN 110
int flag[MAXN/2][MAXN][MAXN];
int ans;
int DFS(int n,int k,int pre){
int i;
int sum = 0;
//if(k == 1) ans ++;
//else if(k == 2) ans += n/k - pre + 1;
if(k == 1) return 1;
else if(k == 2) return n/k - pre + 1;
else {
for(i = pre;i <= n/k;i ++){
if(!flag[i][n - i][k - 1]){
flag[i][n - i][k - 1] = DFS(n - i,k - 1,i);
}
sum += flag[i][n - i][k - 1];
}
}
return sum;
}
int main(){
int n,k;
while(scanf("%d %d",&n,&k) != EOF){
ans = 0;
if(k > n) k = n;
if(!flag[0][n][k]){
flag[0][n][k] = DFS(n,k,0);
}
//printf("%d\n",ans);
printf("%d\n",flag[0][n][k]);
}
return 0;
}