错排问题分析
Posted ych9527
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了错排问题分析相关的知识,希望对你有一定的参考价值。
前言
错排问题,是一种著名且常见的算法,应该熟练掌握它
结合例题进行分析
今年公司年会的奖品特别给力,但获奖的规矩却很奇葩:
- 首先,所有人员都将一张写有自己名字的字条放入抽奖箱中;
- 待所有字条加入完毕,每人从箱中取一个字条;
- 如果抽到的字条上写的就是自己的名字,那么“恭喜你,中奖了!”
现在告诉你参加晚会的人数,请你计算有多少概率会出现无人获奖?
题目链接
分析:
概率 = 每个人拿到的不是自己名字的排列总和 / 每个人有可能拿到的名字的排列总和;
分母,是要求得所有可能出现的情况,很显然是一个全排列问题,即为n!
接下来对分子进行分析:
设f(n)表示有n个人时,错排的方式
1.第一个人,先将其错排 -> 将他放在 2~n的位置上,总共有n-1种方法
2.假设第一个人放的位置是k,加下来再对k进行分析:
a.可以将k放在1的位置,那么剩余n-2个元素的排列方法为 f(n-2)
b.不将k放在1的位置,接下来剩余 n-1个元素和n-1个位置,此时可以将第1个位置看成第k个位置,即将要放在第k个位置的元素,可以放到第一个位置上,此时有f(n-1)种方法 -> 完成第二步的方法为 f(n-1) + f(n-2 )
完成一二步的所有方法为 (n-1) * [f(n-1) + f(n-2) ]
综上所述:
f(n) = (n-1)*[f(n-1) + f(n-2 )] 当 n=1时,f(1)=0; n=2时,f(2)=1;
实现代码:
#include <iostream>
using namespace std;
double GetSum(int n)//获得所有的排列数
{
if(n<3)
return n;
return n*GetSum(n-1);
}
double GetNum(int n)//获得排错的总数
{
if(n==1)
return 0;
if(n==2)
return 1;
return (n-1)*(GetNum(n-2)+GetNum(n-1));
}
int main()
{
double n;
while(cin>>n)
{
double num=GetNum(n)/GetSum(n)*100;
printf("%.2f%\\n",num);
}
return 0;
}
以上是关于错排问题分析的主要内容,如果未能解决你的问题,请参考以下文章