DP或搜索——POJ 1664

来源:互联网 发布:治疗法术升级数据 编辑:程序博客网 时间:2024/06/06 03:56

对应POJ 题目:点击打开链接

放苹果
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 27273 Accepted: 17307

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

17 3

Sample Output

8

思路1:假设dp(m, n) 表示m个苹果放入n个盘子共有的方法数,那么有:

当n > m时,dp(m, n) == dp(m, m),因为有n - m个盘子肯定是空的;

当n <= m时,如果所有的盘子都不为空,则dp(m, n) == dp(m - n, n),它相当于从每个盘子里拿走一个苹果后的方法数,不会影响结果;如果有一个盘子是空的,则dp(m, n) == dp(m, n-1),它相当于把m个苹果放入n-1个盘子的方法数;加起来就是 dp(m, n) = dp(m - n, n) + dp(m, n - 1)。 


思路2:先假设把m个苹果放入1个盘子里(不允许有空盘子,后面一样),有k1种,再把m个苹果放入2个盘子里,有k2种,...,一直到把m个苹果放入n个盘子里,有kn种,那k1 + k2 + ... + kn 就是答案。求ki的方法就是枚举。


思路1代码:

#include <stdio.h>#include <stdlib.h>#include <string.h>int Dfs(int m, int n){if(0 == m || 1 == n) return 1;else if(m >= n) return Dfs(m - n, n) + Dfs(m, n - 1);else return Dfs(m, m);}int main(){freopen("in.txt", "r", stdin);int T, m, n;scanf("%d", &T);while(T--){scanf("%d%d", &m, &n);int cnt = Dfs(m, n);printf("%d\n", cnt);}return 0;}

思路2代码:

#include <stdio.h>#include <stdlib.h>#include <string.h>int cnt;void Dfs(int val, int cur, int sum, int n, int m){if(cur == n){if(sum == m) cnt++;return;}int i;for(i = val; i <= m; i++){if(sum + i > m) break;Dfs(i, cur + 1, sum + i, n, m);}}int main(){//freopen("in.txt", "r", stdin);int T, m, n;scanf("%d", &T);while(T--){cnt = 0;scanf("%d%d", &m, &n);int i;for(i = 1; i <= n; i++)Dfs(1, 0, 0, i, m); //计算kiprintf("%d\n", cnt);}return 0;}







0 0
原创粉丝点击