社区
数据结构与算法
帖子详情
请问高手们:怎么才可以直接输出组合啊??
mis98ZB
2002-01-31 02:36:43
有两种情况:
1。不放回抽样,从N个数中任选M个的所有组合。(M<=N)
2。放回抽样,每次从N个数中选一个,选M次的所有组合。(M=N好象是一个突变点)
唉,数学学的太菜了,老大们,帮忙补补课啊!
...全文
98
5
打赏
收藏
请问高手们:怎么才可以直接输出组合啊??
有两种情况: 1。不放回抽样,从N个数中任选M个的所有组合。(M<=N) 2。放回抽样,每次从N个数中选一个,选M次的所有组合。(M=N好象是一个突变点) 唉,数学学的太菜了,老大们,帮忙补补课啊!
复制链接
扫一扫
分享
转发到动态
举报
AI
作业
写回复
配置赞助广告
用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
打赏
举报
回复
除了生成排列、并检测重复以外,有什么别的妙门吗?
带你快速看完9.8分神作《Effective Java》—— 通用编程篇
???? Java学习:Java从入门到精通总结 ???? Spring系列推荐:Spring源码解析 ???? 最近更新:2021年12月16日 ???? 个人简介:通信工程本硕????、朝着优质博主努力????。我写的很慢,但敢保证每一篇都是用心写的,绝对不无聊,欢迎关注我共饮一杯鸡汤~ ???? 点赞 ???? 收藏 ⭐留言 ???? 都是我最大的动力! 豆瓣评分9.8的图书《Effective Java》,是当今世界顶尖
高手
Josh Bloch的著作,在我之前的文章里我也提到过,编程就像练
英伟达RTX 5070评测解禁:老黄承诺4090级性能?不存在的
机器之心报道编辑:泽南、杜伟价格低了点,功耗高了点,性能和原来差不多?昨晚,英伟达 GeForce RTX 5070 显卡正式解禁,各种评测开始进入人们的视线。我们知道,最近英伟达 RTX 50 系显卡的实际表现引发了不少争议,出现了核心单元丢失、供电等多种问题。在最新登场的主流型号 5070 上,会有一次反转吗?在 1 月初 CES 2025 发布 GeForce RTX 5070 时,黄仁勋表...
世界上最难的 5 种编程语言!网友看后惊讶道:竟不是C/C++?
尽管如此,那些勇于接受挑战的程序员仍然会被它的独特性和神秘感所吸引,他们将投入时间和精力来理解和掌握这门语言,为了解锁其中的奥秘,他们将不断探索和创造。在学习编程的过程中,C、Java和Python这些主流编程语言常常被人们热议,但其实还有一些非常高端的语言,它们通常只有真正的编程
高手
才能搞得懂,这些语言叫做深奥编程语言,简称esolang。它要求你在代码里加"PLEASE",不加会报错,说你不礼貌,但是如果你"PLEASE"用多了,它又会说你太客气了,继续报错,这不是存心找茬吗?
【深度学习】知乎高赞:深度学习如何调参?
深度学习如何调参?看看高赞的回答:高赞回答一 作者:Towser链接:https://www.zhihu.com/question/41631631/answer/862075836总结一...
数据库优化从入门到进阶:SQL Server 数据太多?我来帮你搞定!
嘿,数据存得多是不是一件好事?没错!不过,当你的 SQL Server 数据库开始不堪重负、响应慢得像蜗牛,甚至查询都卡顿到怀疑人生的时候,就需要一些“数据瘦身”操作啦!今天就带你走进SQL Server 优化的世界,让你的数据库不仅存得多,还跑得飞快!✨这篇文章不仅会告诉你如何提升 SQL Server 的性能,更会从多角度分享数据库优化的技巧和实战案例。读完,你一定能有所收获,告别“数据超载”的烦恼!💪SQL Server 的优化是个“技术活”,需要我们用心去琢磨和调试。
数据结构与算法
33,027
社区成员
35,335
社区内容
发帖
与我相关
我的任务
数据结构与算法
数据结构与算法相关内容讨论专区
复制链接
扫一扫
分享
社区描述
数据结构与算法相关内容讨论专区
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章