- 论坛徽章:
- 0
|
原帖由 mcemil 于 2009-8-10 17:53 发表
我知道一种非递归的高效率的球组合数方法,基本描述如下(没有证明,但经过acm的多次考验都是正确的)
假设5个元素取3个,以数组s表示该位置上的元素是否被选中,1选中,0没有选中。
初始为 ,表示第一个组合为 ...
你说的是这个吧,网上找的,有点问题,不过我已经调试好了,还加了打印,文件记录,代码风格很不好,再整理下
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "stdafx.h"
- /***********************
- * 计算一个集合的组合
- **********************/
- #include<stdlib.h>
- /*输出某个组合*/
- void OutputCom(FILE *fp,const int elements[], int *flags, int length)
- {
- int i;
-
- for(i=0; i<length; i++)
- {
- if(flags[i]==1)
- {
- //printf("%d ",elements[i]);
- fprintf(fp, "%u ",elements[i] );
- }
- }
- //printf("\n");
- fprintf(fp, "\n");
- }
- /*计算组合*/
- int GenCom(FILE *fp,const int elements[], int setLg, int k)
- //elements:集合元素; setLg:集合长度; k:从集合中要选取的元素个数
- {
- if(k>setLg || k<=0)
- return -1;
-
- int i,j; //循环变量
- int has10; //是否有"10"组合的标志:1-有;0-无
- int bound; //第一个"10"组合的索引
- int num1; //"10"组合左边的"1"的个数
- int *flags = (int *)malloc(setLg*sizeof(int));//与元素集合对应的标志:1-被选中;0-未被选中
- //初始化,将标志的前k个元素置1,表示第一个组合为前k个数
- printf("正在生成......\n");
- for(i=0; i<k; i++)
- flags[i]=1;
- for(i=k; i<setLg; i++)
- flags[i]=0;
-
- OutputCom(fp,elements, flags, setLg);//输出初始化的组合
- /*
- 从左到右扫描标志的"10"组合,找到第一个"10"组合后将其变为"01"组合,同时将其左边的所有"1"全部移动到数组的最左端
- */
- while(1)
- {
- num1 = 0;
- has10= 0;
- for(i=0; i<setLg-1; i++)
- {
- if(flags[i]==1 && flags[i+1]==0)//找到第一个"10"组合
- {
- bound = i;
-
- flags[i]=0;//将该"10"组合变为"01"组合
- flags[i+1]=1;
-
- for(j=0; j<num1; j++)//将其左边的所有"1"全部移动到数组的最左端
- {
- flags[j]=1;
- }
- for(j=num1; j<bound; j++)
- {
- flags[j]=0;
- }
-
- has10 = 1;
- break;
- }
- else if(flags[i]==1)
- {
- num1++;
- }
- }
- if(has10==0)//没有"10"组合了,代表组合计算完毕
- break;
- OutputCom(fp,elements, flags, setLg);
- }
-
- return 1;
- }
- int ComputeCom( int nSpaceNum, int nElemNum )
- {
- int j;
- int denominator = 1;
- int numerator = 1;
- int nCompNum = 1;
- if ( 0 == nElemNum )
- {
- return 1;
- }
- if ( nElemNum > nSpaceNum / 2 + 1)
- {
- nElemNum = nSpaceNum - nElemNum;
- }
- //计算单个组合的个数
- for( j = 1; j <= nElemNum; j++ )
- {
- numerator *= (nSpaceNum - (j-1));
- denominator *= j;
- }
- nCompNum = numerator / denominator;
- return nCompNum;
- }
- /*测试*/
- int main()
- {
- int dwAllComNum;
- FILE *fp;
- const int elements[33]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33};
- int setLg=33;
- fp = fopen("f:/All.txt","w");
- if (NULL == fp)
- {
- printf("打开文件失败");
- return -1;
- }
- dwAllComNum = ComputeCom(33,6);
- printf("共有 %d 种组合\n",dwAllComNum);
- getchar();
- GenCom(fp,elements, setLg, 6);
- fclose(fp);
- printf("运行完毕\n");
- getchar();
- return 0;
- }
复制代码 |
|