//递归方法
intb[M];
combine(a,N,M,b,M);
return0;
}
由上述分析可知,解决组合问题的通用算法不外乎递归和回溯两种。
在针对具体问题的时候,因为递归程序在递归层数上的限制,对于大型组合问题而言,递归不是一个好的选择,这种情况下只能采取回溯的方法来解决。
n个数的全排列问题相对简单,可以通过交换位置按序枚举来实现。
STL提供了求某个序列下一个排列的算法next_permutation,其算法原理如下:
1.从当前序列最尾端开始往前寻找两个相邻元素,令前面一个元素为*i,后一个元素为*ii,且满足*i<*ii;
2.再次从当前序列末端开始向前扫描,找出第一个大于*i的元素,令为*j(j可能等于ii),将i,j元素对调;
3.将ii之后(含ii)的所有元素颠倒次序,这样所得的排列即为当前序列的下一个排列。
其实现代码如下:
template
boolnext_permutation(BidirectionalIteratorfirst,BidirectionalIteratorlast)
{
if(first==last)returnfalse;//空範圍
BidirectionalIteratori=first;
++i;
if(i==last)returnfalse;//只有一個元素
i=last;//i指向尾端
--i;
for(;;)
{
BidirectionalIteratorii=i;
--i;
//以上,鎖定一組(兩個)相鄰元素
if(*i<*ii)//如果前一個元素小於後一個元素
{
BidirectionalIteratorj=last;//令j指向尾端
while(!
(*i<*--j));//由尾端往前找,直到遇上比*i大的元素
iter_swap(i,j);//交換i,j
reverse(ii,last);//將ii之後的元素全部逆向重排
returntrue;
}
if(i==first)//進行至最前面了
{
reverse(first,last);//全部逆向重排
returnfalse;
}
}
}
下面程序演示了利用next_permutation来求取某个序列全排列的方法:
intmain()
{
intia[]={1,2,3,4};
vectoriv(ia,ia+sizeof(ia)/sizeof(int));
copy(iv.begin(),iv.end(),ostream_iterator(cout,""));
cout<while(next_permutation(iv.begin(),iv.end()))
{
copy(iv.begin(),iv.end(),ostream_iterator(cout,""));
cout<}
return0;
}
注意:
上面程序中初始序列是按数值的从小到大的顺序排列的,如果初始序列无序的话,上面程序只能求出从当前序列开始的后续部分排列,也就是说next_permutation求出的排列是按排列从小到大的顺序进行的。
1。
最近一直在考虑从m个数里面取n个数的算法。
最容易理解的就是递归,但是其效率,实在不能使用。
一直找寻中,今日得果
2。
算法来源与互联网
组合算法
本程序的思路是开一个数组,其下标表示1到m个数,数组元素的值为1表示其下标
代表的数被选中,为0则没选中。
首先初始化,将数组前n个元素置1,表示第一个组合为前n个数。
然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为
“01”组合,同时将其左边的所有“1”全部移动到数组的最左端。
当第一个“1”移动到数组的m-n的位置,即n个“1”全部移动到最右端时,就得
到了最后一个组合。
例如求5中选3的组合:
11100//1,2,3
11010//1,2,4
10110//1,3,4
01110//2,3,4
11001//1,2,5
10101//1,3,5
01101//2,3,5
10011//1,4,5
01011//2,4,5
00111//3,4,5
全排列算法
从1到N,输出全排列,共N!
条。
分析:
用N进制的方法吧。
设一个N个单元的数组,对第一个单元做加一操作,满N进
一。
每加一次一就判断一下各位数组单元有无重复,有则再转回去做加一操作,没
有则说明得到了一个排列方案。
//////////////////////////////////////////////////////
递归算法
全排列是将一组数按一定顺序进行排列,如果这组数有n个,那么全排列数为n!
个。
现以{1,2,3,4,5}为
例说明如何编写全排列的递归算法。
1、首先看最后两个数4,5。
它们的全排列为45和54,即以4开头的5的全排列和以5开头的4的全排列。
由于一个数的全排列就是其本身,从而得到以上结果。
2、再看后三个数3,4,5。
它们的全排列为345、354、435、453、534、543六组数。
即以3开头的和4,5的全排列的组合、以4开头的和3,5的全排列的组合和以5开头的和3,4的全排列的组合.
从而可以推断,设一组数p={r1,r2,r3,...,rn},全排列为perm(p),pn=p-{rn}。
因此perm(p)=r1perm(p1),r2perm(p2),r3perm(p3),...,rnperm(pn)。
当n=1时perm(p}=r1。
为了更容易理解,将整组数中的所有的数分别与第一个数交换,这样就总是在处理后n