排列 && 组合
最近编程经常遇到需要 排列&&组合(求子集) 的问题:遂整理一下。
1. 数字的排列与组合(递归):O(n!),O(nC(n,k)) * O(n)
#include <stdio.h>
int arr[100];
void init(int N)
{
for(int i = 0; i < N; ++i)
arr[i] = i+1;
}
void print(int a[], int n)
{
for(int i = 0; i < n; ++i)
printf("%d ", a[i]);
printf("\n");
} void permutation(int arr[], int begin, int end)
{
if(begin == end) { print(arr, end); return; }
for(int start = begin; start < end; ++start)
{
int t = arr[begin];
arr[begin] = arr[start];
arr[start] = t;
permutation(arr, begin+1, end);
arr[start] = arr[begin];
arr[begin] = t;
}
}
void combination(int endNum, int curNum, int begin, int end, int a[])
{
if(curNum == endNum) { print(a, endNum); return; }
for(int i = begin; i <= end; ++i)
{
a[curNum] = i;
combination(endNum, curNum+1, i+1, end, a);
}
}
int main()
{
int N;
scanf("%d", &N); printf("Combination: \n");
int a[30] = {0};
for(int numberOfElem = 1; numberOfElem <= N; ++numberOfElem)
combination(numberOfElem, 0, 1, N, a); init(N);
printf("Permutation:\n"); permutation(arr, 0, N);
return 0;
}
2. 字符的排列组合
#include <stdio.h>
#include <string.h>
char s[] = "ABC"; void print(const char a[], int n)
{
for(int i = 0; i < n; ++i)
printf("%c ", a[i]);
printf("\n");
} void permutation(char s[], int begin, int end)
{
if(begin == end) { print(s, end); return; }
for(int start = begin; start < end; ++start)
{
char t = s[begin];
s[begin] = s[start];
s[start] = t;
permutation(s, begin+1, end);
s[start] = s[begin];
s[begin] = t;
}
}
void combination(int endNum, int curNum, int begin, int end, char a[], const char s[])
{
if(curNum == endNum) { print(a, endNum); return; }
for(char i = begin; i < end; ++i)
{
a[curNum] = s[i];
combination(endNum, curNum+1, i+1, end, a, s);
}
}
int main()
{
int N = strlen(s); printf("Combination: \n");
char a[30] = {0};
for(int members = 1; members <= N; ++members)
combination(members, 0, 0, N, a, s); printf("Permutation:\n");
permutation(s, 0, N);
return 0;
}
3.数字的组合(非递归)Θ(n2n) * O(n):
#include <stdio.h>
unsigned long long count = 1; int main()
{
int n, k, i, j, c;
scanf("%d", &n);
for(k = 1; k <= n; ++k)
{
for (i=0; i<(1<<n); i++)
{
for (j=0,c=0; j<32; j++) if (i & (1<<j)) c++;
if (c == k)
{
for (j=0;j<32; j++) if (i & (1<<j)) printf ("%i ", j+1);
printf ("\n");
++count;
}
}
}
printf("total: %d\n", count);
}
另外:http://www.cnblogs.com/autosar/archive/2012/04/08/2437799.html 写的不错,可以学习一下。
8月29号。
忽然想起来小时候经常玩的快算 24.
试着利用全排列算法,写了个快算24的小程序。效果还不错。
思想:1、4个数字全排列,对每一个排列,从头到尾计算一遍。共 4!* 43次计算 。 2、 取出所有的两两组合,2 * C(4,2) 种方案, 共 2 * C(4,2) * 43次计算;但是利用全排列,对于每一个排列,取前两个和后两个组合整好是 2 * C(4,2) = 4!种方案。 故总计算复杂度为: 4! * 43 = 42 * 64 = 2688 次(* 2)。
#include <iostream>
using namespace std;
const int v = 24;
int A[4];
const char ch[4] = { '+', '-', '*', '/'};
bool has_answer = false;
int compute(const char ch, int v1, int v2) {
switch(ch) {
case '+': return v1+v2;
case '-': return v1 > v2 ? v1-v2 : -10000;
case '*': return v1*v2;
default:
{
if(v2 == 0) return -10000;
float tem = (float)(v1)/v2;
int tem2 = v1 / v2;
if(abs(tem-tem2) > 0) return -10000;
return tem2;
};
}
}
bool compute24() {
int l, m, n;
for(l = 0; l < 4; ++l) {
int v2 = compute(ch[l], A[0], A[1]);
for(m = 0; m < 4; ++m) {
int v3 = compute(ch[m], v2, A[2]);
for(n = 0; n < 4; ++n) {
if(has_answer) return true;
if(compute(ch[n], v3, A[3]) == v) {
cout << "[ [" << A[0] << ' ' << ch[l] << ' ' << A[1] << "] " << ch[m] << ' '
<< A[2] << " ] " << ch[n] << ' ' << A[3] << " = " << v << endl;
return has_answer = true;
}
else if(compute(ch[m], v2, compute(ch[n], A[2], A[3])) == v) {
cout << "[ " << A[0] << ' ' << ch[l] << ' ' << A[1] << " ] " << ch[m] << " [ "
<< A[2] << ' ' << ch[n] << ' ' << A[3] << " ] = " << v << endl;
return has_answer = true;
} }
}
}
return has_answer;
} void permutation(int begin) {
if(begin == 4) {
compute24();
return;
}
for(int start = begin; start < 4; ++ start) {
int tem = A[start];
A[start] = A[begin];
A[begin] = tem;
permutation(begin+1);
A[begin] = A[start];
A[start] = tem;
}
} int main() {
while(true) {
has_answer = false;
for(int k = 0; k < 4; ++k) {
cin >> A[k];
}
permutation(0);
if(!has_answer) cout << "No solution." << endl;
}
system("pause");
return 0;
}
准备的测试用例: {9, 10, 5, 2}, {5, 6, 7, 9}, {5, 5, 5, 5}, {7, 11, 9, 13}, {3, 7, 11, 3}, {9, 5, 6, 2}, {5, 6, 9, 11}, {10, 11, 2, 2}
使用随机数生成:
/* modify the function main(), as follows: */
int main() {
while(true) {
has_answer = false;
srand((unsigned)time(NULL));
for(int k = 0; k < 4; ++k) {
A[k] = rand() % 14 + 1;
cout << A[k] << ' ';
}
cout << endl; Sleep(10000);
permutation(0);
if(!has_answer) cout << "No solution." << endl;
Sleep(10000);
}
system("pause");
return 0;
}
排列 && 组合的更多相关文章
- 学习sql中的排列组合,在园子里搜着看于是。。。
学习sql中的排列组合,在园子里搜着看,看到篇文章,于是自己(新手)用了最最原始的sql去写出来: --需求----B, C, F, M and S住在一座房子的不同楼层.--B 不住顶层.C 不住底 ...
- .NET平台开源项目速览(11)KwCombinatorics排列组合使用案例(1)
今年上半年,我在KwCombinatorics系列文章中,重点介绍了KwCombinatorics组件的使用情况,其实这个组件我5年前就开始用了,非常方便,麻雀虽小五脏俱全.所以一直非常喜欢,才写了几 ...
- 【原创】开源.NET排列组合组件KwCombinatorics使用(三)——笛卡尔积组合
本博客所有文章分类的总目录:本博客博文总目录-实时更新 本博客其他.NET开源项目文章目录:[目录]本博客其他.NET开源项目文章目录 KwCombinatorics组件文章目录: 1. ...
- 【原创】开源.NET排列组合组件KwCombinatorics使用(二)——排列生成
本博客所有文章分类的总目录:本博客博文总目录-实时更新 本博客其他.NET开源项目文章目录:[目录]本博客其他.NET开源项目文章目录 KwCombinatorics组件文章目录: 1. ...
- 【原创】开源.NET排列组合组件KwCombinatorics使用(一)—组合生成
本博客所有文章分类的总目录:本博客博文总目录-实时更新 本博客其他.NET开源项目文章目录:[目录]本博客其他.NET开源项目文章目录 KwCombinatorics组件文章目录: 1. ...
- hdu1521 排列组合(指数型母函数)
题意: 有n种物品,并且知道每种物品的数量ki.要求从中选出m件物品的排数. (全题文末) 知识点: 普通母函数 指数型母函数:(用来求解多重集的排列问题) n个元素,其中a1,a2, ...
- [leetcode] 题型整理之排列组合
一般用dfs来做 最简单的一种: 17. Letter Combinations of a Phone Number Given a digit string, return all possible ...
- 排列组合算法(PHP)
用php实现的排列组合算法.使用递归算法,效率低,胜在简单易懂.可对付元素不多的情况. //从$input数组中取$m个数的组合算法 function comb($input, $m) { if($m ...
- iOS多线程中,队列和执行的排列组合结果分析
本文是对以往学习的多线程中知识点的一个整理. 多线程中的队列有:串行队列,并发队列,全局队列,主队列. 执行的方法有:同步执行和异步执行.那么两两一组合会有哪些注意事项呢? 如果不是在董铂然博客园看到 ...
- leetcode-Combinations 复习复习排列组合
Combinations 题意: 根据给定的n和k,生成从1到n范围内长度为k的排列组合 示例: n=4 k=2 [[1, 2], [1, 3], [1, 4], [2, 1], [2, 3], [2 ...
随机推荐
- Python collections 模块用法举例
Python作为一个“内置电池”的编程语言,标准库里面拥有非常多好用的模块.比如今天想给大家 介绍的 collections 就是一个非常好的例子. 1.collections模块基本介绍 我们都知道 ...
- minicom的安装与配置
分类: LINUX 如果项目中使用的bootloader为 u-boot,那么在用minicom向目标板传送kernel时 会发生一些错误.故若您使用的是u-boot,建议您使用kermit, ...
- css盒子模型层级3D图
作为前端开发工程师,大家都应该知道盒子模型.下面用一张图来表达3D盒子模型的层级关系 大家可以看到background-color 在background-image的下一层.这个希望对大家有帮助
- web前端基础篇⑥
LESS.①是一种拓展技术,基于css.②包含变量.混合.函数.运算.③简化css代码.降低维护成本④目前用的解析器(koala) 变量(值可变)@变量名:值步骤:①建立文件夹②建html和less两 ...
- Certificate、Provisioning Profile、App ID
关于 Certificate.Provisioning Profile.App ID 的介绍及其之间的关系 2014-03-13 15:26 13416人阅读 评论(1) 收藏 举报 目录(?)[ ...
- UVA 247 电话圈 (floyd传递闭包 + dfs输出连通分量的点)
题意:输出所有的环: 思路:数据比较小,用三层循环的floyd传递闭包(即两条路通为1,不通为0,如果在一个环中,环中的所有点能互相连通),输出路径用dfs,递归还没有出现过的点(vis),输出并递归 ...
- php轮流排序,每隔一定的时间轮流进行位置排序,轮询的排行榜:function dataPollingInterval()
/* * @名称: php ,对数组每隔一定的时间(自设定时间)来轮流进行位置排序,轮询的排行榜. 精确到指定的秒 或 分钟 或 小时 或 天 ,对数据列表进行轮排. * @参数: (array)$l ...
- C++嵌入Python,以及两者混用
以前项目中是C++嵌入Python,开发起来很便利,逻辑业务可以放到python中进行开发,容易修改,以及功能扩展.不过自己没有详细的研究过C++嵌入python的细节,这次详细的研究一下.首先我们简 ...
- 多线程、多进程、协程、缓存(memcache、redis)
本节内容: 线程: a:基本的使用: 创建线程: 1:方法 import threading def f1(x): print(x) if __name__=='__main__': t=thread ...
- 使用JavaScript设置、获取父子页面中的值
一:获取父页面中的值 有二种方法windows.open()和windows.showModalDialog() 1.windos.open(URL,name,reatures,replace) 再父 ...