排列组合递归算法
#include<stdio.h>
#include<string.h>
void
Show(int
n,int
len
,char
str[],
char
p[],int
*i)
{
/*函数功能说明: 密码穷举法
递归算法
参数说明:
len
密码可选元素的个数,实际等于
strlen(str);
n
密码位数。
STR[]密码表。
*p
密码排列组合的临时存档
*/
int
a;
n--;
for(a=0;
a
<
len;
a++)
{
p[n]=str[a];
if(n==0)printf("%d:%s
",(*i)++,p);
if(n>0)Show(n,len
,
str,p,i);
}
} /*驱动程序
用于测试*/
int
main(void)
{
char
str[]="abcdef";//密码表
可选元素集合可根据选择修改
int
n=4; //密码位数,根据具体应用而定。
int
len=strlen(str);//用于密码元素集合计数。
char
p[20]; //存放排列组合的密码,用于输出。
int
num=0;//存放统计个数的整数值,
int
*i=#//计数器
地址。
p[n]='\0';//这个不用说啦。 Show(
n,len
,str,
p
,i);
printf("\n%d
位密码,每个密码有%d个选择的话,共有:%d个组合。\n",n,len,*i); return
0;
}
2. 递归算法的设计
#include <stdio.h>
int C(int n,int m)
{ if(m==0||m==n)return 1;
return C(n-1,m)+C(n-1,m-1);
}
int main()
{ int i,j;
for(i=0; i<11; i++)
{ for(j=0; j<=i; j++)
printf("%5d",C(i,j));
printf(" ");
}
return 0;
}
3. 排列组合算法,要求从一堆数中任取m个数组合使得m个数的和最接近某个数
典型的组合问题,解法有递归、回溯等等递归法较简单,代码如下: void combine(int a[], int n, int m, int b[], int M); 参数:a 存放候选数字n 总项数m 取出项数b 存放选出结果M = m
#include "stdio.h"#define MAX 100 void combine(int a[], int n, int m, int b[], int M); int main(void){ int i; int a[MAX], b[MAX]; for (i = 1; i < 100; i++) a[i - 1] = i; combine(a, 5, 4, b, 4);} void combine(int a[], int n, int m, int b[], int M){ int i, j; for (i = n; i >= m; i--) { b[m - 1] = i - 1; if (m > 1) combine(a, i - 1, m - 1, b, M); else { for (j = M - 1; j >= 0; j--) printf("%d ", a[b[j]]); printf("\n"); } }}
其他方法可查阅相关资料。
4. 设计递归算法生成n个元素的所有排列对象
#include<iostream>
#include<iterator>
#include<algorithm>
using namespace std;
template<class T>
void permutation(T list[], int k, int m)
{
if (k == m)
{
(list, list + m + 1, ostream_iterator<T>(cout, "")); //将当前list排序
cout << endl;
}
else{
for (int i = k; i <= m; i++)
{
swap(list[i], list[k]); //将下标为i的元素交换到k位置,类似从list[k:m]中剔除操作
permutation(list, k + 1, m);
swap(list[i], list[k]);
}
}
}
int main(int argc, char* argv[])
{
char arr[3] = { 'a', 'b', 'c' };
cout << "排序结果如下:" << endl;
permutation(arr, 0, 2);
return 0;
}
(4)排列组合递归算法扩展阅读
递归,在数学与计算机科学中,是指在函数的定义中使用函数自身的方法。也就是说,递归算法是一种直接或者间接调用自身函数或者方法的算法。
通俗来说,递归算法的实质是把问题分解成规模缩小的同类问题的子问题,然后递归调用方法来表示问题的解。
递归的基本原理
第一:每一级的函数调用都有自己的变量。
第二:每一次函数调用都会有一次返回。
第三:递归函数中,位于递归调用前的语句和各级被调用函数具有相同的执行顺序。
第四:递归函数中,位于递归调用后的语句的执行顺序和各个被调用函数的顺序相反。
第五:虽然每一级递归都有自己的变量,但是函数代码并不会得到复制。
5. c语言编程排列组合
void Show(int n,int len ,char str[], char p[],int *i){/*函数功能说明:
密码穷举法 递归算法参数说明:len 密码可选元素的个数,实际等于 strlen(str);
n 密码位数。
STR[]密码表。
*p 密码排列组合的临时存档*/int a;n--;for(a=0; a < len; a++){p[n]=str[a];
if(n==0)printf("%d:%s ",(*i)++,p);
if(n0)Show(n,len , str,p,i);}}
/*驱动程序 用于测试*/
int main(void){char str[]="abcdef";//密码表 可选元素集合可根据选择修改
int n=4;//密码位数,根据具体应用而定。
int len=strlen(str);//用于密码元素集合计数。
char p[20];//存放排列组合的密码,用于输出。
int num=0;//存放统计个数的整数值,
int *i=#//计数器 地址。
p[n]='\0';//这个不用说啦。
printf("\n%d 位密码,每个密码有%d个选择的话,共有:%d个组合。\n",n,len,*i);return 0;}
以上回答你满意么?
6. 排列组合中A和C怎么算啊
1、排列组合中,组合的计算公式为:
7. 排列组合中c53是怎么算的,5在下,3在上
C(5,3)=C(5,2)=5*4/2*1=20/2=10
1、从n个不同元素中,任取m(m≤n)个元素并成一组,叫做从n个不同元素中取出m个元素的一个组合;从n个不同元素中取出m(m≤n)个元素的所有组合的个数,叫做从n个不同元素中取出m个元素的组合数。
2、在线性写法中被写作C(n,m)。组合数的计算公式为
即从m个不同元素中取出n个元素的组合数=从m个不同元素中取出 (m-n) 个元素的组合数;
这个性质很容易理解,例如C(9,2)=C(9,7),即从9个元素里选择2个元素的方法与从9个元素里选择7个元素的方法是相等的。
规定:C(n,0)=1 C(n,n)=1 C(0,0)=1
参考资料
网络-组合数
8. pascal排列组合教程
排列与组合
3.1加法原理与乘法原理
1.加法原理:
做一件事情,完成它可以有n类办法,在第一类办法中有m1 种不同的方法,在第二类办法中有 m2种不同的方法,……,在第n类办法中有 mn种不同的方法。那么完成这件事共有 N= m1+m2+...+mn 种不同的方法。
2.乘法原理:
做一件事情,完成它需要分成n个步骤,做第一步有m1 种不同的方法,做第二步有 m2种不同的方法,……,做第n步有 种mn不同的方法,那么完成这件事有 N=m1*m2*...*mn 种不同的方法。
3.两个原理的区别:一个与分类有关,一个与分步有关;加法原理是“分类完成”,乘法原理是“分步完成”。
练习:
1.由数字1,2,3,4,5可以组成多少个三位数(各位上的数字允许重复)?
② 2.由数字0、1,2,3,4,5可以组成多少个三位数(各位上的数字允许重复)?
③ 3.由数字0,1,2,3,4,5可以组成多少个十位数字大于个位数字的两位数?
例 4. 一个三位密码锁,各位上数字由0,1,2,3,4,5,6,7,8,9十个数字组成,可以设置多少种三位数的密码(各位上的数字允许重复)?首位数字不为0的密码数是多少种?首位数字是0的密码数又是多少种?
5.如图,要给地图A、B、C、D四个区域分别涂上3种不同颜色中的某一种,允许同一种颜色使用多次,但相邻区域必须涂不同的颜色,不同的涂色方案有多少种?
6.某班有22名女生,23名男生.
① 选一位学生代表班级去领奖,有几种不同选法?
② 选出男学生与女学生各一名去参加智力竞赛,有几种不同的选法?
7.105有多少个约数?并将这些约数写出来.
8.从5幅不同的国画、2幅不同的油画、7幅不同的水彩画中选不同画种的两幅画布置房间,有几种选法?
9.若x、y可以取1,2,3,4,5中的任一个,则点(x,y)的不同个数有多少?
10.一个口袋内装有5个小球另一个口袋内装有4个小球,所有这些小球的颜色各不相同① 从两个口袋内任取一个小球,有 种不同的取法;
11.从两个口袋内各取一个小球,有 种不同的取法.
12.乘积(a1+a2+a3)(b1+b2+b3+b4)(c1+c2+c3+c4+c5)展开共有 个项。
13.有四位考生安排在5个考场参加考试.有 种不同的安排方法。
(答案:125;180;15;1000,900,100;6;45,506;8;59;25;9;20;60;625)
3. 2 排列与组合的概念与计算公式
1.排列及计算公式
从n个不同元素中,任取m(m≤n)个元素按照一定的顺序排成一列,叫做从n个不同元素中取出m个元素的一个排列;从n个不同元素中取出m(m≤n)个元素的所有排列的个数,叫做从n个不同元素中取出m个元素的排列数,用符号 p(n,m)表示.
p(n,m)=n(n-1)(n-2)……(n-m+1)= n!/(n-m)!(规定0!=1).
2.组合及计算公式
从n个不同元素中,任取m(m≤n)个元素并成一组,叫做从n个不同元素中取出m个元素的一个组合;从n个不同元素中取出m(m≤n)个元素的所有组合的个数,叫做从n个不同元素中取出m个元素的组合数.用符号
c(n,m) 表示.
c(n,m)=p(n,m)/m!=n!/((n-m)!*m!);c(n,m)=c(n,n-m);
3.其他排列与组合公式
从n个元素中取出r个元素的循环排列数=p(n,r)/r=n!/r(n-r)!.
n个元素被分成k类,每类的个数分别是n1,n2,...nk这n个元素的全排列数为
n!/(n1!*n2!*...*nk!).
k类元素,每类的个数无限,从中取出m个元素的组合数为c(m+k-1,m).
练习:
1.(1)用0,1,2,3,4组合多少无重复数字的四位数?(96)
(2)这四位数中能被4整除的数有多少个?(30)
(3)这四位数中能被3整除的数有多少个?(36)
2.用0,1,2,3,4五个数字组成无重复数字的五位数从小到大依次排列.
(1) 第49个数是多少?(30124)
(2) 23140是第几个数?(40)
3.求下列不同的排法种数:
(1) 6男2女排成一排,2女相邻;(p(7,7)*p(2,2))
(2) 6男2女排成一排,2女不能相邻;(p(6,6)*p(7,2))
(3) 5男3女排成一排,3女都不能相邻;(p(5.5)*p(6,3))
(4) 4男4女排成一排,同性者相邻;(p(4,4)*p(4,4)*p(2,2))
(5) 4男4女排成一排,同性者不能相邻。(p(4,4)*p(4,4)*p(2,2))
4.有四位医生、六位护士、五所学校。
(1) 若要选派三位医生到五所学校之中的三所学校举办健康教育讲座,每所学校去一位医生有多少种不同的选派方法?(c(5,3)*p(4,3))
(2) 在医生或护士中任选五人,派到五所学校进行健康情况调查,每校去且仅去一人,有多少种不同的选派方法?(p(10,5))
(3) 组成三个体检小组,每组一名医生、两名护士,到五所学校中的三所学校为老师体检,有多少种不同的选派方法?(c(5,3)*p(4,3)*c(6,2)*c(4,2)*c(2,2))
5.平面上有三条平行直线,每条直线上分别有7,5,6个点,且不同直线上三个点都不在同一条直线上。问用这些点为顶点,能组成多少个不同四边形?(2250)
6.平面上有三条平行直线,每条直线上分别有7,5,6个点,且不同直线上三个点都不在同一条直线上。问用这些点为顶点,能组成多少个不同三角形?(751)
7.将N个红球和M个黄球排成一行。例如:N=2,M=2可得到以下6种排法:
红红黄黄 红黄红黄 红黄黄红 黄红红黄 黄红黄红 黄黄红红
问题:当N=4,M=3时有多少种不同排法?(不用列出每种排法)(35)
8.用20个不同颜色的念珠穿成一条项链,能做多少个不同的项链.(20!/20)
9.在单词MISSISSIPPI 中字母的排列数是(11!/(1!*4!*4!*2!)
10.求取自1,2,...k的长为r的非减序列的个数为(c(r+k-1,r))
3.3排列与组合的产生算法
1.排列的产生
方法1:(递归,深度优先产生)
程序如下:
program pailei;
const m=4;
var a:array[1..m] of integer ;
b:array[1..m] of boolean;
procere print;
var i:integer;
begin
for i:=1 to m do
write(a[i]);
writeln;
end;
procere try(dep:integer);
var i:integer;
begin
for i:=1 to m do
if b[i] then
begin
a[dep]:=i; b[i]:=false;
if dep=m then print else try(dep+1);
b[i]:=true;
end;
end;
begin
fillchar(b,sizeof(b),true);
try(1);
end.
方法2.根据上一个排列产生下一个排列.
程序如下:
program pailei;
const m=5;
var a:array[1..m] of integer ;
i,j,temp,k,l:integer;
procere print;
var i:integer;
begin
for i:=1 to m do
write(a[i]);
writeln;
end;
begin
for i:=1 to m do a[i]:=i;
repeat
print;
i:=m-1;
while (i>0) and (a[i]>a[i+1]) do i:=i-1;
if i>0 then
begin
j:=m;
while a[j]<a[i] do j:=j-1;
temp:=a[i];a[i]:=a[j];a[j]:=temp;
k:=i+1;l:=m;
while k<l do
begin
temp:=a[k];a[k]:=a[l];a[l]:=temp;
k:=k+1;l:=l-1
end;
end;
until i=0;
end.
2.组合的产生算法
算法1:(递归,深度优先产生)
程序如下:
program zuhe;
const n=6;m=4;
var a:array[0..m] of integer;
i,j:integer;
procere print;
var i:integer;
begin
for i:=1 to m do write(a[i]);
writeln;
end;
procere try(dep:integer);
var i:integer;
begin
for i:=a[dep-1]+1 to n-(m-dep) do
begin
a[dep]:=i;
if dep=m then print else try(dep+1);
end
end;
begin
a[0]:=0;
try(1);
end.
算法2:根据前一个组合产生下一个组合
程序如下:
program zuhe;
const n=6;m=4;
var a:array[1..m] of integer;
i,j:integer;
procere print;
var i:integer;
begin
for i:=1 to m do write(a[i]);
writeln;
end;
begin
for i:=1 to m do
a[i]:=i;
repeat
print;
i:=m;
while (i>0) and (a[i]=n-(m-i)) do dec(i);
if i>0 then
begin
a[i]:=a[i]+1;
for j:=i+1 to m do a[j]:=a[j-1]+1;
end;
until i=0;
end.
练习:
1.已知n(1<=n<=20)个整数x1,x2,…,xn(1<=xi<=5000000),以及一个整数k(k<n)。从n个整数中任选k个整数相加,可分别得到一系列的和。现在,要求你计算出和为素数共有多少种。
2.n个部件,每个部件必须经过先A后B两道工序。
以知部件i在A,B 机器上的时间分别为ai,bi。如何安排加工顺序,总加工时间最短?
输入:
5 部件 1 2 3 4 5
ai 3 5 8 7 10
bi 6 2 1 4 9
输出:
34
1 5 4 2 3
我有这个的EXE,讲的东西也还行,这个只是其中的一章,你要要把邮箱留下
9. 设计递归算法生成n个元素的所有排列对象
#include<iostream>
#include<cmath>
using namespace std;
int count(int n)
//算n的阶乘——因为n个数能组成n!个数
{
if(n<1)
{
cout<<"输入也错!";
exit(0);
}
else
if(n==1)
return 1;
else
return count(n-1)*n;
}
int pow10(int n)
//算出10的n次方
{
int a;
if(n==0)
return 1;
else
for(int i=1;i<=n;i++)
a=10*pow10(n-1);
return a;
}
int * comm(int n)
//组合n!个数(这里用递归算)
{
int *a=new int[count(n)];
if(count(n)==1)
a[0]=1;
else
{
int *b=new int[count(n-1)];
b=comm(n-1);
for(int i=0;i<count(n-1);i++)
for(int j=0;j<n;j++)
a[i*n+j]=(b/pow10(j)*10+n)*pow10(j)+b%pow10(j);
}
return a;
}
void main()
{
int n;
cout<<"请输入n=";
cin>>n;
int *a=new int[count(n)];
a=comm(n);
cout<<"1-"<<n<<"自然数所有的排列组合为:\
";
for(int i=0;i<count(n);i++)
cout<<a<<" ";
}
=======================================
#define MAX 1000
#include<stdio.h>
void DispArrangement(int a[MAX], int n, int deepth)
{
int i, temp;
if(deepth == 1) {
for(i = 1; i <= n; i ++) {
printf("%d", a);
}
printf("\
");
} else {
for(i = 1; i <= deepth; i ++ ){
temp = a[n - deepth + 1];
a[n - deepth + 1] = a[n - deepth + i];
a[n - deepth + i] = temp;
DispArrangement(a, n, deepth - 1);
temp = a[n - deepth + 1];
a[n - deepth + 1] = a[n - deepth + i];
a[n - deepth + i] = temp;
}
}
}
int main(void)
{
int i, n, a[MAX];
scanf("%d", &n);
for(i = 1; i <= n; i ++ ) {
a = i;
}
DispArrangement(a, n, n);
return 0;
}