码迷,mamicode.com
首页 > 其他好文 > 详细

盒子放球

时间:2015-10-22 21:23:18      阅读:211      评论:0      收藏:0      [点我收藏+]

标签:

盒子放球问题

第一类:

将k个球放入n个不同的盒子中,每个盒子放球数>=0,求方法数

假设n个盒子分别放x1,x2,x3...xn,则x1+x2+x3+...+xn=k,令yi=xi+1(1<=i<=n),则yi>=1y1+y2+...+yn=n+k,相当于求yi这个方程的解组数,可以看成插板问题,往n+k个物品中插入n-1个板,所以答案是C(n+k-1,n-1)=C(n+k-1,k)

/*
 *输入说明:k个相同的球放入n个不同的盒子
 *输入每行有两个正整数n和k
 */
int com(int n, int m) {
    m = min(m, n - m);
    int res = 1;
    for (int i = 0, j = 1; i < m; i ++) {
        res *= n - i;
        while (j <= m && res % j == 0) {
            res /= j;
            j ++;
        }
    }
    return res;
}

int main() {

    int n, k;
    while (~scanf("%d %d", &n, &k)) {
        printf("%d\n", com(n+k-1, k));
    }

    return 0;
}

 

第二类:

m个相同的球放入n个相同的盒子,每个盒子放球数>=0,求方法数

令dp[i][j]表示i个球放入j个盒子的方法数。

当i>j时,分两种情况:

1、每个盒子至少放一个,为dp[i-j][j]

2、存在某个盒子不放,为dp[i][j-1]

所以dp[i][j] = dp[i-j][j] + dp[i][j-1];

当i<=j时,等价于i个球放入i个盒子

const int maxn = 20;

int dp[maxn][maxn];//i个球放入j个盒子方法数

void init() {
    for (int j = 1; j <= 10; j ++) dp[0][j] = dp[1][j] = dp[j][1] = dp[j][0] = 1;
    for (int i = 2; i <= 10; i ++) {
        for (int j = 2; j <= 10; j ++) {
            if (i >= j) dp[i][j] = dp[i-j][j] + dp[i][j-1];
            else dp[i][j] = dp[i][i];
        }
    }
}

int main() {

    init();
    int T, m, n;
    scanf("%d", &T);
    while (T --) {
        scanf("%d %d", &m, &n);
        printf("%d\n", dp[m][n]);
    }
    return 0;
}

 

 

盒子放球

标签:

原文地址:http://www.cnblogs.com/LinKArftc/p/4902594.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!