知识储备
1.排列
排列的定义:从n个不同元素中,任取m(m≤n,m与n均为自然数,下同)个元素按照一定的顺序排成一列,叫做从n个不同元素中取出m个元素的一个排列;从n个不同元素中取出m(m≤n)个元素的所有排列的个数,叫做从n个不同元素中取出m个元素的排列数,用符号 A(n,m)表示
计算公式:
注意:m中取n个数,按照一定顺序排列出来,排列是有顺序的,就算已经出现过一次的几个数。只要顺序不同,就能得出一个排列的组合,例如1,2,3和1,3,2是两个组合。
2.组合
组合的定义:从n个不同元素中,任取m(m≤n)个元素并成一组,叫做从n个不同元素中取出m个元素的一个组合;从n个不同元素中取出m(m≤n)个元素的所有组合的个数,叫做从n个不同元素中取出m个元素的组合数。用符号 C(n,m) 表示。
计算公式:
注意:m中取n个数,将他们组合在一起,并且顺序不用管,1,2,3和1,3,2其实是一个组合。只要组合里面数不同即可
组合算法
0-1转换组合算法摘自:http://blog.chinaunix.net/uid-20684578-id-1572099.html
本算法的思路是开两个数组,一个index[n]数组,其下标0~n-1表示1到n个数,1代表的数被选中,为0则没选中。value[n]数组表示组合的数值,作为输出之用。
- 首先初始化,将index数组前m个元素置1,表示第一个组合为前m个数,后面的置为0。
- 然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为 “01”组合,同时将其左边的所有“1”全部移动到数组的最左端。一起得到下一个组合(是一起得出,是一起得出,是一起得出)
- 重复1、2步骤,当第一个“1”移动到数组的n-m的位置,即m个“1”全部移动到最右端时;即直到无法找到”10”组合,就得到了最后一个组合。
组合的个数为:
例如求5中选3的组合:
1 1 1 0 0 //1,2,3
1 1 0 1 0 //1,2,4
1 0 1 1 0 //1,3,4
0 1 1 1 0 //2,3,4
1 1 0 0 1 //1,2,5
1 0 1 0 1 //1,3,5
0 1 1 0 1 //2,3,5
1 0 0 1 1 //1,4,5
0 1 0 1 1 //2,4,5
0 0 1 1 1 //3,4,5
代码如下:
#include <iostream>
using namespace std;
void Show(int ,int index[],int value[]);
bool judge(int,int ,int index[]);
void change(int ,int ,int index[],int value[]);
int main()
{
int i,n,m;
cout<<"请输入元素个数:";
cin>>n;
cout<<"请输入选多少元素:";
cin>>m;
int index[n]={0},value[n]; //index务必初始化为0,不然无法知道m个数之后里面是真还是假
for(i=0;i<n;i++)
{
value[i]=i+1;//此处是赋初值,以1,2,3,4,5为例,当然任何数字都可以
}
change(n,m,index,value);
return 0;
}
void Show(int n,int index[],int value[])
{
int i;
for(i=0;i<n;i++)
{
if(index[i]) cout<<value[i]<<" ";
}
cout<<endl;
}
bool judge(int n,int m,int index[])
{
int i;
for(i=n-1;i>=n-m;i--)
{
if(!index[i]) return false;
}
return true;
}
void change(int n,int m,int index[],int value[]) //核心算法函数
{
int i,j,num=0;
for(i=0;i<m;i++)
{
index[i]=1;
}
Show(n,index,value); //第一个组合
num +=1;
while(!judge(n,m,index)) //只要没使1全部移到右边,就继续循环
{
for(i=0;i<n-1;i++) //注意是n-1,因为i=n-1时,i+1是不存在的
{
//找到10,变成01
if(index[i]==1&&index[i+1]==0)
{
index[i]=0;
index[i+1]=1;
//将01组合左边的1全部放在数组最左边
int count=0;
for(j=0;j<i;j++)
{
if(index[j])
{
index[j]=0;
index[count++]=1;
}
}
Show(n,index,value); //输出
num +=1;
break;
}
}
}
cout<<"共有"<<num<<"种"<<endl;
}