高分求算法--高手请进来

bluehunters 2004-04-04 11:18:56
编写算法求从n个数里面取m个数的所有组合。
...全文
4 点赞 收藏 12
写回复
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
zfangla 2004-04-05
//从n个数中,选m个的排列。
void swap(int& a,int& b);
void fun(int list[],int k,int n,int m)
{//list[],数组。k:扫描号。n:总数。m:选取个数。
int i;
if(k==m+1)
{
for(i=1;i<=m;i++)
cout<<list[i]<<"\t";
cout<<endl;
}
else
for(i=k;i<=n;i++)
{
swap(list[k],list[i]);
fun(list,k+1,n,m);
swap(list[k],list[i]);
}
}
void swap(int& a,int& b)
{
int i=a;a=b;b=i;
}
void main()
{
int list[4]={0,4,5,6};//因为第1个元素从list[1]开始。
fun(list,1,3,2);
}
回复
bluehunters 2004-04-05
谢谢大家,我自己写了一个,已经搞定了,还是用的递归。
和你们给我提供的大同小异。我是在求全排列的时候控制一下,
只保留升序的结果。这样就得到组合了。
因为我的那几个数是自然数的子集,且没有重合的。
所以也能解决。就是功能的通用性不强。
而且好像效率也不高,因为每次求组合的时候必须先求出排列来。
总之,还是谢谢各位的关注。
回复
bluehunters 2004-04-05
还有好一点的方法么?
谢谢!
回复
7111925 2004-04-05
从n个数中取m个数,当第一个数字选定时,就变成从n-1个数中取m-1个数了,当计算出一种组合时,再一起输出。
回复
showjancn 2004-04-05
弟归法如下(这是个全排列,你只需稍做修改即呆):
///////////////////////
#include "iostream.h"

static int count = 0;
const int size = 3;
int MyArr1[size];
int MyArr2[size];

void Arr(int N);
int MayStand(int N, int i);
void InitArr();
void PrintOut();

void Arr(int N)
{
if(N==0)
{
count ++;
PrintOut();
}
else
{
for (int i=0; i<size; i++)
{
if (MayStand(N,i))
{

MyArr2[N-1] = MyArr1[i];
Arr(N-1);
}
}
}
}

int MayStand(int N, int i)
{
for (int j=size; j>N; j--)
{
if (MyArr2[j-1] == MyArr1[i])
{
return 0;
}
}

return 1;
}

void InitArr()
{
for (int i=0; i<size; i++)
{
MyArr1[i] = i;
}
for (i=0; i<size; i++)
{
MyArr2[i] = 0;
}
}

void PrintOut()
{
for (int i=0; i<size; i++)
{
cout<<" "<<MyArr2[i];
}
cout<<endl;
}

void main()
{
InitArr();
Arr(size);

cout<<count<<endl;
}
回复
pcyy 2004-04-05
up
回复
zfangla 2004-04-05
写得很烂,应该用类包装。我写程序很冗于,我写程序没注释。不过运行正确。看不懂问我,一定细心解答。还有,希望高手给出组合的更优算法。
回复
zfangla 2004-04-05
//从n个数中,选m个的组合。
int **output,n1,n2,cur;
void swap(int& a,int& b);
void filter(int tmp[],int *output[])
{
int isok=1,i;
for( i=0;i<cur+1;i++)
{
int same_num=0;
for(int j=0;j<n2;j++)
{
for(int f=0;f<n2;f++)
if(tmp[f]==output[i][j])
same_num++;
}
if(same_num==n2)
isok=0;
}
if(isok==1)
{
cur++;
for(i=0;i<n2;i++)
output[cur][i]=tmp[i];
}
}
void fun(int list[],int k,int n,int m)
{//list[],数组。k:扫描号。n:总数。m:选取个数。
int i;
if(k==m+1)
{
int* tmp=new int[m];
for(i=1;i<=m;i++)
tmp[i-1]=list[i];
filter(tmp,output);
}
else
for(i=k;i<=n;i++)
{
swap(list[k],list[i]);
fun(list,k+1,n,m);
swap(list[k],list[i]);
}
}
void swap(int& a,int& b)
{
int i=a;a=b;b=i;
}
void main()
{
int list[4]={0,4,5,6};//因为第1个元素从list[1]开始。
n1=3*2/2;
n2=2;
cur=-1;
output=new int*[n1];
for(int v=0;v<n1;v++)
output[v]=new int[n2];

fun(list,1,3,2);
for(int i=0;i<n1;i++)
{
for(int j=0;j<n2;j++)
cout<<output[i][j]<<"\t";
cout<<endl;
}
}
回复
7111925 2004-04-04
递归

回复
yyf_ty 2004-04-04
是只需要总数么?那不就是:n*(n-1)*.......(n-m+1)/(m*(m-1)*....*2*1)么?:)
回复
bluehunters 2004-04-04
呵呵,不是算数,是找出所有的组合。也可以理解为打印所有集合。
我想用递归可能行,不知道各位大侠有什么好的意见??
谢谢。
回复
hcj2002 2004-04-04
从n个数里面取m个数的所有组合的算法??

高中数学中有。


关键是楼主要打印所有集合,还是只输出集合的总数,如果是前者就比较麻烦。
回复
发动态
发帖子
VC/MFC
创建于2007-09-28

1.5w+

社区成员

VC/MFC相关问题讨论
申请成为版主
社区公告
暂无公告