排列与组合的应用Word文件下载.docx
《排列与组合的应用Word文件下载.docx》由会员分享,可在线阅读,更多相关《排列与组合的应用Word文件下载.docx(31页珍藏版)》请在冰豆网上搜索。
从k个不同元素{a1a2…ak}中取n个元素按次序排列,元素ai可以取ri次,r1+r2+...+rk=r,这样的排列称为有限重排列。
实际上,这个问题与下面的问题等价:
把r(r1+r2+...+rk=r)只彩色球放到n个编号不同的盒子中去的方法数
如r=n,则排列数有
(5)错排问题
一个排列使得所有的元素都不在原来的位置上,则称这个排列为错排。
例如有3个元素,原来位置为:
123,它的错排有两种312和231。
用f[n]表示n个元素的错排数,利用容斥原理可以推出(过程略):
f[n]=
主要讲一下递推式。
考虑任意一个满足条件的排列a1,a2,a3,…,an,显然有an≠n,不妨设n=ai,考虑书i的位置,它有两种情况:
1)i=an
2)i≠an
对于1),数i在位置n,而数n在位置i上,则是n-2的错排问题,这种情况的方法数为f[n-2]。
对于2),可以把位置n看成位置i(位置i上不放数i,而此时位置n也不放数i,所以i和n可以等同看待),则问题成了n-1个数的错排问题了。
由1)与2)及i有n-1种取值,所以有f[n]=(n-1)(f[n-2]+f[n-1])。
:
2.组合及公式
(1)非重组合
一般地,从n个不同元素中,取出m(m≤n)个元素,不允许元素重复,不考虑元素次序,叫做从n个不同元素中取出m个元素的一个非重组合;
从n个不同元素中取出m(m≤n)个元素的所有组合的个数,叫做从n个不同元素中取出m个元素的组合数.用符号
表示.
组合数的两个性质:
(2)重组合
从n个不同元素中,取出r个允许重复的元素而不考虑其次序时,称为从n个不同元素中取r个允许重复的组合,简称重组合。
其组合数为
.
这个问题,可以看作用r个相同的标记去标明这n个不同的对象,而每一个对象可以被标上多个标记,一个对象上最多r个标记。
设n个元素为{a1a2…an},记ai被记了k次为ai(k),同一个元素标记不同次数,认为是不同的元素,那么第1次标记有n种方法,有n+1个元素{a1a2…anai(k)},第2次标记就有n+1种方法,有n+2个元素,……第r次标记有n+r-1种方法,有n-r个元素,而标记顺序对结果没有影响,所以有
种方法,即
二、排列与组合生成算法
1.排列生成
有N本不同的书摆在书架上,设其编号分别为1,2,3,......,N,编程求解这N本书的不同摆放方案和摆放方案总数。
程序名:
pailie.pas/c/cpp 输入文件:
pailie.in 输出文件:
pailie.out
输入文件的格式为:
仅为一个数N
输出文件的格式为:
依次为每一行为一种方案,每个数之间用一个空格隔开,最后一行为方案数
样例
input
2
output
12
21
数据规模 1=<
N<
=10
说明,排列方案字典顺序小的在前。
分析:
本题要求出所有具体方案,所以用不着排列公式来计算方案数。
生成排列方案的过程中可以统计出方案总数。
(1)按字典序生成排列法(根据上一个排列产生下一个排列)。
该算法的N—S流程图如图1。
Pascal版参考程序:
programpailie;
var
s,j,t,i,k,n:
Longint;
a:
array[1..10]oflongint;
functionfi:
longint;
i:
begin
=n;
while(i>
1)and(a[i-1]>
a[i])dodec(i);
fi:
=i;
end;
functionfk:
k:
while(k>
1)and(a[k]<
a[i-1])dodec(k);
fk:
=k;
procedureprint;
inc(s);
fori:
=1ton-1dowrite(a[i],'
'
);
writeln(a[n]);
begin
assign(input,'
pailie.in'
assign(output,'
pailie.out'
reset(input);
rewrite(output);
readln(n);
=1tondoa[i]:
s:
=0;
print;
=fi;
whilei>
1do
=fk;
t:
=a[i-1];
a[i-1]:
=a[k];
a[k]:
=t;
forj:
=ito(n+i)div2do
=a[n+i-j];
a[n+i-j]:
=a[j];
a[j]:
writeln(s);
close(input);
close(output);
end.
(2)回溯算法产生排列
用p[i]记录一个排列的第i个数,
伪代码描述的产生排列的第i个数的方法
Proceduretry(i)
Begin
Ifi>
nthenbegin输出排列;
返回 end;
//产生了一个完整排列,输出
Forj=1tondo
Ifnota[j]then //j这个数没有用
Begin
P[i]=j;
A[j]=true;
//占位
Try(i+1);
//搜索下一个数
End;
var
p:
array[1..10]oflongint;
array[1..10]ofboolean;
n,tot,i:
fil:
text;
procedureprint;
inc(tot);
=1tondo
write(fil,p[i],'
writeln(fil);
proceduretryy(i:
longint);
j:
ifi>
nthenbeginprint;
exitend;
ifnota[j]then
=true;
p[i]:
=j;
tryy(i+1);
=false;
assign(fil,'
reset(fil);
readln(fil,n);
close(fil);
rewrite(fil);
fillchar(a,sizeof(a),false);
tot:
tryy
(1);
writeln(fil,tot);
C语言版参考程序:
#include<
stdio.h>
longa[15],n,s;
boolf[15];
FILE*fp;
voidshu(longa[])
{
longi;
for(i=1;
i<
i++)
fprintf(fp,"
%d"
a[i]);
\n"
s++;
}
voidpai(longi)
longj,k;
if(i==n+1){shu(a);
return;
}
for(j=1;
j<
j++)
if(f[j]){f[j]=false;
a[i]=j;
pai(i+1);
f[j]=true;
}
intmain()
longi,j,k,m;
fp=fopen("
pailie.in"
"
r"
fscanf(fp,"
%d"
&
n);
pailie.out"
w"
i++)f[i]=true;
s=0;
pai
(1);
%d\n"
s);
fclose(fp);
return0;
2.组合生成
有N本不同的书摆在书架上,设其编号分别为1,2,3,......,N,现要从其中取出R本书,编程求解这N本书的不同组合方案和方案总数。
zuhe.pas/c/cpp 输入文件:
zuhe.in 输出文件:
zuhe.out
仅为一行,两个数N和R,之间用一个空格隔开
依次为每一行为一种组合,每个数之间用一个空格隔开,最后一行为组合方案数
32
13
23
3
N,R<
=30
说明,每一种组合,从小到大排列;
组合方案字典顺序小的在前
本题要求出所有具体方案,所以用不着组合公式来计算方案数。
生成组合方案的过程中可以统计出方案总数。
(1)根据上一个组合产生下一个组合。
该算法的N—S流程图如图2。
programzuhe;
c:
array[1..30]oflongint;
n,r,i,j,tot:
=1tordo
write(fil,c[i],'
functionfindi:
=r;
while(