社区
数据结构与算法
帖子详情
请问高手们:怎么才可以直接输出组合啊??
mis98ZB
2002-01-31 02:36:43
有两种情况:
1。不放回抽样,从N个数中任选M个的所有组合。(M<=N)
2。放回抽样,每次从N个数中选一个,选M次的所有组合。(M=N好象是一个突变点)
唉,数学学的太菜了,老大们,帮忙补补课啊!
...全文
85
5
打赏
收藏
请问高手们:怎么才可以直接输出组合啊??
有两种情况: 1。不放回抽样,从N个数中任选M个的所有组合。(M<=N) 2。放回抽样,每次从N个数中选一个,选M次的所有组合。(M=N好象是一个突变点) 唉,数学学的太菜了,老大们,帮忙补补课啊!
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
5 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
mis98ZB
2002-02-01
打赏
举报
回复
万分感谢版主starfish(海星)的代码!!!
先仔细研究一下,有不懂的地方还望指教。
也感谢intfree()和shshsh_0510()的指点。
资料一下子多了起来,先看看,
想清楚了再提问。
starfish
2002-02-01
打赏
举报
回复
现在是不是流行用计算机算体育彩票呀~~
怎么这么多人问这个问题,sigh~~
下面的代码是我写的用来计算组合数的一个类:
#ifndef _COMBINATION_H_
#define _COMBINATION_H_
/*
combination.h
这个头文件定义了一个Combinatin类
利用该类可以生成从m个数中取出n个数的组合数
并且过滤出满足一定条件的组合数
注意,这里的m, n 都必须是0~255之间的整数
*/
#include <iostream>
#include <iomanip>
#include <vector>
#include <list>
using namespace std;
typedef unsigned char byte;
typedef vector<byte> ByteArray;
class Combination : public list<ByteArray>
{
protected:
byte m, n; // 生成从m个数中取出n个数的组合
vector<bool> enabled; // 用来标记1~m中哪些数字可以使用
ByteArray LowBound, HighBound; // 记录组合数中每一位的可取值范围
bool repeatable; // 标记生成的组合数中的数字是否可以重复出现
protected:
// 回溯搜索组合数的第i位
void SearchComb(int i, ByteArray& L);
public:
/*
功能: 类Combination的构造器
参数: m 组合数中每一位可取得最大整数
n 组合数的位数
说明:
例如,如果要生成从整数1~30中取出7个整数的组合数,
应该声明如下:
Combination combs(30, 7);
*/
Combination(byte m, byte n);
/*
功能:设置组合数中第i位的取值范围
参数:i 设置组合数中第i位数的取值范围,1 <= i <= n
lbound 取值下界, 1 <= lbound <= m
hbound 取值上界, 1 <= hbound <= m
说明:
例如,如果要设置组合数的1位取值范围为3~5
则应该调用:
SetBound(1, 3, 5);
如果要固定组合数的第一位为4,则应该调用
SetBound(1, 4, 4);
注意:
1. 这里的i从1开始计数
2. 如果参数i, lbound, hbound超出了允许的范围,
则调用该方法不会有任何结果
3. 组合数中每一位的默认取值范围是1~m,如果原来设置了
第i位的取值范围,现在想取消原来的设置,则应该调用:
SetBound(i, 1, m);
*/
void SetBound(byte i, byte lbound, byte hbound);
// 清除原来设置的所有的取值范围
void ResetAllBound();
// 在组合数中禁用数字x
void Disable(byte x);
// 在组合数中禁用从a到b所有的数字
void Disable(byte a, byte b);
// 在组合数中重新允许使用数字x
void Enable(byte x);
// 在组合数中重新允许使用从a到b所有的数字
void Enable(byte a, byte b);
// 生成组合数
void GenerateCombination();
// 设置组合中的数字是否可以重复
void SetRepeatable(bool repeatable);
// 这是一个虚函数
// 可以在派生类中加入你自己的过滤器
virtual void Filter() { }
};
// 回溯搜索组合数的第i位
// 注意,搜索出的组合数是从小到大排列的
void Combination::SearchComb(int i, ByteArray& L) {
if (i == n) {
this->push_back(L);
} else {
int begin;
if (i == 0) {
begin = LowBound[i];
} else {
begin = LowBound[i];
if ( (repeatable == false) && (LowBound[i] < L[i-1] + 1) ) {
begin = L[i-1] + 1;
}
}
for (int j = begin; j <= HighBound[i]; j++) {
if (enabled[j]) {
if (repeatable == false) enabled[j] = false;
L[i] = j;
SearchComb(i+1, L);
if (repeatable == false) enabled[j] = true;
}
}
}
}
/*
功能: 类Combination的构造器
参数: m 组合数中每一位可取得最大整数
n 组合数的位数
说明:
例如,如果要生成从整数1~30中取出7个整数的组合数,
应该声明如下:
Combination combs(30, 7);
*/
Combination::Combination(byte m, byte n) {
this->m = m;
this->n = n;
this->repeatable = false;
LowBound.resize(n);
HighBound.resize(n);
ResetAllBound();
enabled.resize(m + 1);
Enable(1, m);
}
/*
功能:设置组合数中第i位的取值范围
参数:i 设置组合数中第i位数的取值范围,1 <= i <= n
lbound 取值下界, 1 <= lbound <= m
hbound 取值上界, 1 <= hbound <= m
说明:
例如,如果要设置组合数的1位取值范围为3~5
则应该调用:
SetBound(1, 3, 5);
如果要固定组合数的第一位为4,则应该调用
SetBound(1, 4, 4);
注意:
1. 这里的i从1开始计数
2. 如果参数i, lbound, hbound超出了允许的范围,
则调用该方法不会有任何结果
3. 组合数中每一位的默认取值范围是1~m,如果原来设置了
第i位的取值范围,现在想取消原来的设置,则应该调用:
SetBound(i, 1, m);
*/
void Combination::SetBound(byte i, byte lbound, byte hbound) {
if( lbound >= 1 && hbound <= m && i >= 1 && i <= n) {
i--;
LowBound[i] = lbound;
HighBound[i] = hbound;
}
}
// 清除原来设置的所有的取值范围
void Combination::ResetAllBound() {
for (int i = 0; i < n; i++) {
LowBound[i] = 1;
HighBound[i] = m;
}
}
void Combination::Disable(byte x) {
if (x >=1 && x <= m) {
enabled[x] = false;
}
}
void Combination::Disable(byte a, byte b) {
for (byte i = a; i <= b; i++) {
Disable(i);
}
}
void Combination::Enable(byte x) {
if (x >=1 && x <= m) {
enabled[x] = true;
}
}
void Combination::Enable(byte a, byte b) {
for (byte i = a; i <= b; i++) {
Enable(i);
}
}
// 设置组合中的数字是否可以重复
void Combination::SetRepeatable(bool repeatable) {
this->repeatable = repeatable;
}
// 生成组合数
void Combination::GenerateCombination() {
ByteArray L(n); // 用来存储每一组的组合数
this->clear();
SearchComb(0, L); // 搜索组合数
Filter(); // 调用过滤器进行过滤
}
// 重载输出运算符
ostream operator<<(ostream& out, const ByteArray& array) {
for (int i = 0; i < array.size(); i++) {
out<< setw(4) << int( array[i] );
}
return out;
}
ostream operator<<(ostream& out, const Combination& combs) {
list<ByteArray>::const_iterator iter;
for (iter = combs.begin(); iter != combs.end(); iter++) {
out << *iter << endl;
}
out << "Total count is : " << combs.size() << endl;
return out;
}
#endif
下面是一个测试用的例子 test.cpp:
#include "combination.h"
#include <vector>
#include <algorithm>
using namespace std;
class MyCombs : public Combination
{
private:
// 这个过滤器将求出组合数中两两相减的值
// 如果所有不重复的差值总数等于一个常数X则保留该组合
// 否则删除该组合
void Filter_A() {
const int X = 18;
list<ByteArray>::iterator iter;
for( iter = this->begin(); iter != this->end(); )
{
ByteArray& array = *iter;
vector<int> temp; // 注意,temp一定要在这个for循环里面声明
// 下面这个二重for循环用来求两辆相减的绝对值,并且把不重复的元素放在temp中
for(int i = 0; i < array.size(); i++ ) {
for( int j = i+1; j < array.size(); j++ ) {
int d = abs(int(array[i]) - int(array[j]));
// 如果在temp中找不到该差值
if( find( temp.begin(), temp.end(), d) == temp.end() ) {
temp.push_back(d);
}
}
}
// 直接判断temp中的元素的数目就可以了,因为原来temp中的值都是互不相同的
if( temp.size() != 18 ) {
list<ByteArray>::iterator old_iter = iter;
iter++;
this->erase(old_iter);
} else {
iter++;
}
}
}
void Filter_B() {
// 可以在这里加入你自己的过滤器
}
public:
MyCombs(byte m, byte n) :
Combination(m, n)
{
}
// 覆盖父类的虚方法,
// 在这个函数中填入你自己的过滤器即可
// 如果有多个过滤器,将其写成函数,
// 在这个函数中一一调用即可
void Filter() {
//Filter_A();
// 你也可以加上Filter_B(); Filter_C()...., etc
}
};
int main()
{
MyCombs combs(4, 3);
combs.SetBound(1, 1, 4);
combs.SetBound(2, 1, 4);
combs.SetBound(3, 1, 4);
combs.SetRepeatable(true);
combs.GenerateCombination();
cout << "result is : " << endl;
cout << combs << endl;
return 0;
}
intfree
2002-01-31
打赏
举报
回复
我记得starfish的主页上就有,
而且这个问题在csdn上出现过多次了,
你可以搜索前面的帖子。
good luck!
shshsh_0510
2002-01-31
打赏
举报
回复
卢开澄的《组合数学》中有好几种生成算法:
mis98ZB
2002-01-31
打赏
举报
回复
除了生成排列、并检测重复以外,有什么别的妙门吗?
职场
高手
必备:学会49个Word高效技巧,告别加班,跑赢95%的同事
带你快速看完9.8分神作《Effective Java》—— 通用编程篇
???? Java学习:Java从入门到精通总结 ???? Spring系列推荐:Spring源码解析 ...豆瓣评分9.8的图书《Effective Java》,是当今世界顶尖
高手
Josh Bloch的著作,在我之前的文章里我也提到过,编程就像练
【深度学习】知乎高赞:深度学习如何调参?
除了gate之类的地方,需要把
输出
限制成0-1之外,尽量不要用sigmoid,可以用tanh或者relu之类的激活函数.1. sigmoid函数在-4到4的区间里,才有较大的梯度。之外的区间,梯度接近0,很容易造成梯度消失问题。2. 输入0...
动态规划2-和ACM大牛的对话
学习DP过程中的一些和大牛交流的心得:差不多就是我理解的一个阶梯过程,为保护隐私,去掉名字了: 石头 16:23:46 ...动态规划是不是一般就是填矩阵?...可以这么理解 石头 16:25:10 ???
PGA零基础学习:FPGA在FPGA中何时用
组合
逻辑或时序逻辑
当
组合
逻辑1无法进行优化时,还想要达到自己想要的速度时,我们可以进行逻辑拆分,增加数据的
输出
潜伏期,增加数据的运行速度。 将
组合
逻辑1的功能拆分为
组合
逻辑A和
组合
逻辑B,此时,输入的数据得到结果虽然会多...
数据结构与算法
33,007
社区成员
35,326
社区内容
发帖
与我相关
我的任务
数据结构与算法
数据结构与算法相关内容讨论专区
复制链接
扫一扫
分享
社区描述
数据结构与算法相关内容讨论专区
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章