详解排列组合
来源:互联网 发布:南京交通驾校 知乎 编辑:程序博客网 时间:2024/06/04 01:01
最近一直在研究搜索问题,发现了一个现象:很多搜索问题本质上其实就是排列组合的问题,只不过加上了某些剪枝和限制条件。在解决诸如此类的问题一般都会用到非空循环排列、全排列、一般组合或全组合。其中不重复排列和不重复组合就是一种剪枝的方法。为了理清自己的思路,同时也为了分享的目的就将自己的想法写下来。
首先说的是非空循环排列。
#include <iostream>using namespace std;const int MAX = 100;int result[MAX];void f(int *array, int arrayLength, int l, int n){if(l==n){for(int i=0; i < n; i++)cout << result[i] << ' ';cout << endl;return ;}for(int i=0; i < arrayLength; i++){result[l] = array[i];f(array, arrayLength, l+1, n);}}int main(){int arrayLength = 5;int array[5]={1,2,3,4,5};int count = 3;f(array, arrayLength, 0, count);return 0;}
全排列,对一个数组进行全排列
#include <iostream>using namespace std;const int MAX = 100;int result[MAX];bool visit[MAX];void f(int *array, int arrayLength, int l, int n){if(l==n){for(int i=0; i < n; i++)cout << result[i] << ' ';cout << endl;return ;}for(int i=0; i < arrayLength; i++){// 如果此值没有被访问过 if(!visit[i]){visit[i] = true;result[l] = array[i];f(array, arrayLength, l+1, n);// 递归回溯用 visit[i] = false;}}}void Init(){for(int i=0; i < MAX; i++)visit[i] = false;}int main(){int array[5]={1,2,3,4,5};int count = 3;Init();f(array, 5, 0, count);return 0;}
在很多时候数据可能出现相等的情况,而我们又不需要相同的数据,那么我们就可以把重复的数据数据排除,这就是不重复排列。在搜索中会当做剪枝用到。
比如:1,1,2
不重复排列之后就是:1,1,2
1,2,1
2,1,1
代码如下:
#include <iostream>using namespace std;const int MAX = 10;int number[MAX], used[MAX], result[MAX];int n;void f(int l){if(l==n){for(int i=0; i < n; i++)cout << result[i] << ' ';cout << endl;return ; }for(int i=0; i < n; i++){if(used[i]>0){used[i]--;result[l] = number[i];f(l+1);used[i]++;}}}void readData(){int count=0, value;cin >> n;for(int i=0; i < n; i++){cin >> value;int j;for(j=0; j < count;j ++){if(number[j]==value){used[j]++;break;}}if(j==count){used[count]=1;number[count++] = value;}}}int main(){readData();cout << "Result is :" << endl;f(0);return 0;}
不重复排列就是对全排列做了一次剪枝,在录入数据的时候用一个数组将真正的数保存起来,并另外用一个数组把每个数出现的次数也保存起来,那么在做递归的时候,在全排列中是判断某一个数是否有没有使用过,而这里其实也是一样,如果出现的次数大于一的话,那么就递减一表明其中一个数已经出现过了。
一般组合:n个数中取m 个数求组合
#include <iostream>using namespace std;const int MAX = 10;int number[MAX], result[MAX];int n, m;void f(int l, int p){if(l==m){for(int i=0; i < m; i++)cout << result[i] << ' ';cout << endl;return ;}for(int i=p; i < n; i++){result[l] = number[i];f(l+1, i+1);}}void readData(){cin >> n >> m;for(int i=0; i < n; i++)cin >> number[i];}int main(){readData();f(0,0);return 0;}
全组合:输出一个集合中所有的子集。2^n
#include <iostream>using namespace std;const int MAX = 10;int number[MAX], result[MAX];int n;void f(int l, int p){for(int i=0;i< l; i++)cout << result[i] <<' ';cout << endl;for(int i=p; i < n; i++){result[l] = number[i];f(l+1, i+1);}}void readData(){cin >> n;for(int i=0; i < n; i++)cin >> number[i];}int main(){readData();f(0,0);return 0;}
不重复的组合
#include <iostream>using namespace std;const int MAX =10;int number[MAX], used[MAX], result[MAX];int n;int count=0;void f(int l,int p){for(int i=0; i < l; i++)cout << result[i] << ' ';cout << endl;for(int i=p; i < count; i++){if(used[i]>0){used[i]--;result[l] = number[i];f(l+1, i);used[i]++;}}}void readData(){int value;cin >> n;for(int i=0; i < n; i++){cin >> value;int j;for(j=0; j < count;j ++){if(number[j]==value){used[j]++;break;}}if(j==count){used[count]=1;number[count++] = value;}}}int main(){readData();f(0,0);return 0;}
7 0
- 详解排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- Android Service运用小例子
- IOS 之 开发的一些小技巧
- 模拟DVD 实现录入 查看 借出 归还 删除 新增 等功能<分层>
- pip“Unable to find vcvarsall.bat”错误解决
- linux下vim命令详解
- 详解排列组合
- ubuntu清理磁盘
- 网站 IIS线程池 处理
- 第十七周上机实践项目——年龄几何
- struts2实现多文件批量上传并手动拦截文件类型和大小
- V4L2视频采集操作流程和接口说明
- linux触摸屏驱动开发中的s3c_ts_probe()函数的分析
- pysnmp安装
- 忘记该忘记的