排列组合 "n个球放入m个盒子"算法 总结

问题:

总结   https://blog.csdn.net/qwb492859377/article/details/50654627

N个球放M个盒子问题   https://blog.csdn.net/zwz_511/article/details/46240927

 

 

算法:

HDU - 6397 Character Encoding 插板法+容斥原理  https://blog.csdn.net/xiang_6/article/details/81868989

[ACM] POJ 1664 放苹果(n个相同小球放入m个相同盒子)  https://blog.csdn.net/sr_19930829/article/details/38293297

m个相同的bean和n棵不同的树,每棵树可以放也可以不放beans  https://blog.csdn.net/moon_sky1999/article/details/81835284

n个球放入m个盒子,使用程序输出所有的放法?   https://www.zhihu.com/question/51448931

 

递归解

#include
using namespace std;
void Select(int i,int j,const int m,int *x,int &num){//i为第i个盒子。0<=i<=m-1。j是剩余球数。x为放置球的解法,num可有可无,记录放置的方法数目。
    if (i > m)
        return;
    if (j == 0){
        num++;
        cout << "x可行序列为 : (";
        for (int i = 0; i < m; i++){
            cout << x[i];
            if (i != m - 1)
                cout << ",";
            else
                cout << ")" << endl;
        }
        return;
    }
    for (int k = j; k >= 0; k--){
        if (i == m)
            return;
        x[i] = k;
        Select(i + 1, j - k, m, x,num);
        x[i] = 0;
    }
}
int main(){
    int num = 0;
    int m = 5, n = 3;
    int x[5] = { 0 };
    Select(0, n, m, x,num);
    cout << "共 " << num << "种" << endl;
    return 0;
}

r用于记录当前的结果,p是写入该缓存的位置。那么f(r,p,n,m)的意义就是把n个球放入m个盒子。如果只有一个盒子就打印结果,>1个盒子就放入0至n个球到当前盒子,余下的球和盒子递归调用f()

 

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

题意:

a1 + a2 + ... + am = k , 0 <= ai < n;  给定n m  k 问:上述式子成立的种类数有多少,1+2=3 和 2+1=3 是两种情况

思路:

说到这个题必须要说的是组合数学的隔板法:

①k个相同的小球放入m个不同的盒子,每个盒子不为空的种类数:k-1个空隙中插入m-1个板子,C(k-1, m-1)

②k个相同的小球放入m个不同的盒子,可以允许有的盒子为空种类数:我们再加上m个球,按照①式不为空求解,因为分割完后,每个盒子减去1,就是当前问题的解,即:C(k-1+m, m-1);

 

对于本题,可以理解成k个相同的球放入m个不同的盒子,每个盒子可以为空,但是个数不能大于等于n;

正男则反,我们算总的减去大于等于n个情况的种类数,容斥一下、待更、、

 

#include
using namespace std;
void Select(int i,int j,const int m,int *x,int &num){//i为第i个盒子。0<=i<=m-1。j是剩余球数。x为放置球的解法,num可有可无,记录放置的方法数目。
	if (i > m)
		return;
	if (j == 0){
		num++;
		cout << "x可行序列为 : (";
		for (int i = 0; i < m; i++){
			cout << x[i];
			if (i != m - 1)
				cout << ",";
			else
				cout << ")" << endl;
		}
		return;
	}
	for (int k = j; k >= 0; k--){
		if (i == m)
			return;
		x[i] = k;
		Select(i + 1, j - k, m, x,num);
		x[i] = 0;
	}
}
int main(){
	int num = 0;
	int m = 5, n = 3;
	int x[5] = { 0 };
	Select(0, n, m, x,num);
	cout << "共 " << num << "种" << endl;
	return 0;
}

 

你可能感兴趣的:(生涯)