排列组合的求法&next_permutation
来源:互联网 发布:2016奥运女排数据 编辑:程序博客网 时间:2024/04/30 11:38
即数学上的排列组合,这里提供了两种方式。
第一种是用STL头文件algorithm中的next_permutation或prev_permutation函数。但是这样只能求全排列,不能求组合。这种方法网络上很多讲解的,这里不再赘述。
第二种是自己编写的算法,采用了遍历和回溯。
算法描述如下:
结果存于数组a中
判断a[i]是否符合条件,若符合再判断是否已到第N位,若不符合,再判断a[i]加一还是回到第i-1位继续判断
a[i]的初值是a[i-1]值的下一个值
若a[i]的值与a[i-1]相等时,第i位此轮遍历结束
低位逐次加1,此位遍历结束时,其上一位加1,直到第1位加到N程序结束
数组a的a[0]弃置不用,用以表示排列组合元素的数字从1开始,不使用0
#include <stdio.h>#include <stdlib.h>#define arrange//排列,否则是组合///求解A(N,M)或C(N,M)#define N 4#define M 4int a[N+1] = {0,1};//必须保证a[1]为1int counter = 0;//计算排列或组合数, 注意数目太大时可能溢出///将符合条件的情况输出void show(){ for(int k=1; k<=N; ++k) printf("%d",a[k]); printf(" "); ++counter;}///判断数组a第i位的值是否符合要求bool ismatch(int i){ for(int k=1; k<i; ++k) {#ifdef arrange//排列 if(a[k] == a[i]) return false;#else//组合 if(a[k] >= a[i]) return false;#endif } return true;}///回溯或自加int backtrack(int &i){ if(a[i] == a[i-1])//若a[i]的值已经经过一圈追上a[i-1] { --i;//i值减1,退回处理前一个元素 if(a[i]==M && i>1) a[i] = 1;//当第i位的值达到M时,第i位的值取1 else if(a[i]==M && i==1)//当第一位的值达到M时结束 return 0;//遍历结束,退出程序 else ++a[i];//第i位的值取下一个,加1 } else if(a[i]==M) a[i]=1; else ++a[i]; return 1;}///遍历void ergodic(void){ int i=1; while(1) { if(ismatch(i))//第i位已经满足要求,处理第i+1位 { if(i==N)//i已到达N,获得了一个结果 { show(); if(!backtrack(i)) return; } else//继续处理下一位 { ++i; if(a[i-1] == M) a[i] = 1;//a[i]的初值是a[i-1]值的下一个值 else a[i] = a[i-1] + 1; } } else//第i位不满足要求,需要重新设置:回溯至第i-1位或a[i]加1 if(!backtrack(i)) return; }}int main(void){ ergodic(); printf("\n\n共 %d 种排列/组合.\n",counter); return 0;}
next_permutation
算法:
在当前序列中,从尾端往前寻找两个相邻元素,前一个记为*i,后一个记为*ii,并且满足*i < *ii。然后再从尾端寻找另一个元素*j,如果满足*i < *j,即将第i个元素与第j个元素对调,并将第ii个元素之后(包括ii)的所有元素颠倒排序,即求出下一个序列了。
原型:
template<class BidirectionalIterator>bool next_permutation(BidirectionalIterator _First, BidirectionalIterator _Last);template<class BidirectionalIterator, class BinaryPredicate>bool next_permutation(BidirectionalIterator _First, BidirectionalIterator _Last, BinaryPredicate _Comp);
我以int数组实现这个算法:
template <typename T>void nswap(T *a, T *b){ if(a == b) return; T temp; temp = *a; *a = *b; *b = temp;}//反转序列[first,last)template <typename T>void reverse(T first, T last){ --last; while(last - first > 0) nswap(first++, last--);}//区间为[first,last)bool next_permutation(int *first, int *last){ if(last - first < 2) return false; //只有一个元素或为空 int *ii = last-1; while(!(*(ii-1)<*ii)) { --ii; //已是最大序列,反转一次换到最小序列 if(ii == first) { reverse(first, last); return false; } } int *i = ii-1; int *j = last-1; for(; j!=i; --j) { if(*i < *j) { nswap(i, j); break; } } reverse(ii, last); //置换[ii,last) return true;}
0 0
- 排列组合的求法&next_permutation
- 排列组合之next_permutation函数的运用
- next_permutation(排列组合)函数的用法
- next_permutation(排列组合)函数的用法
- nyoj19(排列组合next_permutation(s.begin(),s.end()))
- STL_算法(17)_排列组合 next_permutation() perv_permutation()
- 求下一个排列组合和前一个排列组合(next_permutation和pre_permutation)
- next_permutation 的使用
- next_permutation的使用
- 排列 next_permutation的应用
- C++STL的next_permutation
- 使用stl的next_permutation
- 关于next_permutation的用法
- next_permutation的使用
- next_permutation的函数
- next_permutation函数的使用
- next_permutation 的使用
- next_permutation函数的应用
- 通过echo将字符串、某个文件文档 加到另外一个文件的末端
- iOS使用CoreLocation API需要的配置
- 如何在 iOS 真机运行 Appium
- Makefile之写demo时的通用Makefile写法总结
- sublime之xdebug浏览器插件
- 排列组合的求法&next_permutation
- MPEG简介
- C#特性
- 微软安装包中 Redistributable 和 runtime 的区别
- 远程连接Oracle数据库
- Quick-Cocos2d-x UI控件之滑动条(UISlider)控件
- 中电信12月运营数据:移动用户1.86亿 3G占63%
- 给不同的按钮设置同样的点击listener,在listener内部根据不同的按钮分别处理
- Android开源:数据库ORM框架GreenDao学习心得及使用总结