| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 9763 人关注过本帖
标题:请教高手从m个数中任取n个数的组合算法(可以重复)
取消只看楼主 加入收藏
myelement
Rank: 1
等 级:新手上路
帖 子:11
专家分:0
注 册:2008-6-10
收藏
 问题点数:0 回复次数:10 
请教高手从m个数中任取n个数的组合算法(可以重复)
我想问问有m个数,如果任意输入n,可以实现m中取n的组合算法,数字可以允许重复。比如有3个数1,2,3,n=3,则一共有111,112,113,221,222,223,331,332,333,123种取法(123,321,231中确只能有1个)。即需要满足公式,C(m,n)=(m+n-1)!/n!(m-1)!,有哪位高手能帮帮忙?想了很久都不得其解,谢谢先!
搜索更多相关主题的帖子: 算法 
2008-06-10 09:46
myelement
Rank: 1
等 级:新手上路
帖 子:11
专家分:0
注 册:2008-6-10
收藏
得分:0 
有没有哪位高手大虾知道啊,想了两个星期了,编的程序只能取出无重复的。谢谢先!!!
2008-06-10 23:02
myelement
Rank: 1
等 级:新手上路
帖 子:11
专家分:0
注 册:2008-6-10
收藏
得分:0 
我现在编的程序可以取出不同数的类似1234,1356和完全重复的1111,2222,最难的就是如何实现有部分重复的比如1122,1113,1145之类的。
2008-06-11 00:05
myelement
Rank: 1
等 级:新手上路
帖 子:11
专家分:0
注 册:2008-6-10
收藏
得分:0 
先谢谢楼上诸位的先!
重复取数字是指每一种取法中数字可以有重复,比如说112,111可以,不过112和121,211却只能出现一次。
我当时只想要结果,不在乎算法,所以我自己编时用的是最笨的方法,一个一个实现。
先是编数字完全没有一样的,象123,234这样的,我用的算法
int a[2000];
int a[1]=1;km=1;
while(n-a[1]>=m)  
    {while(km<m)      
      {km++;  
        a[km]=a[km-1]+1;  
      }  
      for(;a[km]<=n;a[km]++)      
      {kinds++;  
        for(i=1;i<=m;i++)  
            printf("%5d",a[i]);  
        printf("\n");  
      }  
      km--;  
      while(n-a[km]<=m-km)km--;     
    }  
    for(i=n-m+1;i<=n;i++)  
        printf("%5d",i);   
然后编数字完全一样的,这个很容易,把每一个数取n次就可以了,不过最难的就是数字部分有重复的。
另我不是太懂DSF, 是一种数据结构吗?我是学化学的,老板非要我找出20种氨基酸可以组合成哪些种蛋白质,所以还要各位多多指教!
2008-06-11 07:30
myelement
Rank: 1
等 级:新手上路
帖 子:11
专家分:0
注 册:2008-6-10
收藏
得分:0 
呵呵,没有,用了一天的时间在修改你的程序变成我想要的东西,我现在已经解决了组合的问题,非常谢谢泉此方!这个程序简单好用,佩服! 不过我现在发现个新的问题,我想要组合的是字母,每种字母的取法都对应着一个数字,比如说GGG, GGA, GGB 分别对应着20, 20, 30, 然后我想要删除有相同数字的组合,GGG 和GGA 就只能保留一个。 这个应该说不难,建立一个数组,然后循环比较,出现相同的就剔除一个,不过当我从20中取到10以后的时候,就会有几千万甚至几亿个组合(根据公式计算),根本就超出了数组的range,除非能够在一边取的时候,一边就比较,剔除(组合中有大量这种数字相同的)。不过感觉这根本不太可能,有达人有好的建议吗?谢谢!不过我觉得剔除后也大概会有十几万个,还是一样会超出数组的range。遇到这样的情况有什么办法处理呢????谢谢!
2008-06-12 22:42
myelement
Rank: 1
等 级:新手上路
帖 子:11
专家分:0
注 册:2008-6-10
收藏
得分:0 
谢谢泉此方! G,A,B分别是不同的氨基酸, 如果取GAB,对应GAB的数字就是它们质量的加合.因为我要删除质量相同的取法,所以我把每个对应的数字都赋给一个数组,循环剔除,不过现在最多只能运行到取6种的情况.
2008-06-13 01:14
myelement
Rank: 1
等 级:新手上路
帖 子:11
专家分:0
注 册:2008-6-10
收藏
得分:0 
质量和的最大值很小,不超过2000。不剔除质量数字相同的,当取到19的时候,有400 billion个组合,我换了指针,最多也只能运行到12 billion。如果剔除重复的,从1取到19所有组合加起来估计不会超过4 million。
2008-06-13 22:23
myelement
Rank: 1
等 级:新手上路
帖 子:11
专家分:0
注 册:2008-6-10
收藏
得分:0 
[bo][un]Loli[/un] 在 2008-6-13 23:03 的发言:[/bo]


非常非常好,那原来的代码只要极少量的修改就可以轻松做出来了


http://yzfy.

really? 极少量的修改就可以了吗?因为我始终觉得需要先把每一种取法都存放在数组里,第一轮循环(所有后面取法都和第一种取法比较)可能不要,边取就可以比较,筛选,不过第二轮循环,如果不把第二种取法先存起来,怎么和其他比较呢?
2008-06-15 00:04
myelement
Rank: 1
等 级:新手上路
帖 子:11
专家分:0
注 册:2008-6-10
收藏
得分:0 
强!这是什么东东啊?可以解释详细点吗? 谢谢先!!
2008-06-15 00:20
myelement
Rank: 1
等 级:新手上路
帖 子:11
专家分:0
注 册:2008-6-10
收藏
得分:0 
我修改后的代码,谢谢!!!定义的指针,最大只能运行到12 billion.
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include <iostream>
using namespace std;
template<class T>
int DFS_FindNext(T arr[], int nMaxElm, int nDepth)
{
    int n = nDepth-1;
    for (++arr[n]; n>=0 && arr[n]>=nMaxElm; ++arr[--n]);
    if (n<0) return 0;
    for (int t = n+1; t<nDepth; ++t) arr[t] = arr[n];
    return 1;
};
int main()
{
    int n=4,m=19,i,j,v=0,l=0;// 输入m,n
    int arr[20]={0};
    float c1[20],z1[20];
    float *c2,*z2;
    c2=(float *)malloc(1200000000*sizeof(float));
    z2=(float *)malloc(1200000000*sizeof(float));
    c1[0]=0;z1[0]=0;
    char outmap[19]={'A','B','S','P','V','T','C','L','N','D','Q','K','E','M','H','F','R','Y','W'};
    float c[19]={75.055,89.071,105.066,115.087,117.102,119.082,121.043,
    131.1184381,132.045435,133.0171,146.09521,146.12971,147.076,
    149.0748591,155.0932861,165.1027881,174.1354851,181.0977,204.113};
    float z[19]={60.022935,74.03645,90.0405,100.095,102.096,104.3437,106.0007,116.0837297,
  117.0427,118.02687,131.082437,131.0946287,132.0487,134.0407,140.0585777,
    150.06797,159.1067,166.0647,189.0787};
    FILE *fp1;
    fp1=fopen("1.txt","w");
        do
        {
            for(int t=0,i=1;t<n,i<=n;++t,i++)
            {
                fprintf(fp1,"%c",outmap[arr[t]]); //输出字母的组合
               
                 c1[i]=c[arr[t]]+c1[i-1];
                 z1[i]=z[arr[t]]+z1[i-1];
               }            
            fprintf(fp1,"\t%.7f\t%.7f\t%d\n",c1[n],z1[n],v+1);//输出每种字母组合对应的二个数字
            c2[l]=c1[n];z2[l]=z1[n];v++;l++;  //赋予新的数组以便循环比较,问题在于l很大
        }while(DFS_FindNext(arr, m, n));
    return 0;
fclose(fp1);
}
2008-06-16 22:19
快速回复:请教高手从m个数中任取n个数的组合算法(可以重复)
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.038829 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved