什么是错排公式?
首先我们考虑一个问题,如果书架上有n本书,现在希望把每本书都放在不是原来的位置上,那么有几种放置的方法?
上面的问题就是错排问题。
现在,我么来解决:
首先,我们取一本位置在m位置上的书,现在m位置空出来了,现在要放在其他n-1个位置上,假设我们放在了位置k上,那么我们就把k位置上的书拿出来了,现在k位置空出来了,所以现在原本在k位置上的书要放在哪里呢,有两种选择,一种是放在原来的M位置上,还有一种是放在其他的n-2个位置的随便一个,现在我们分析这两种情况:
1:放在m位置上,那就相当于m位置上的书和K位置上的书交换了位置,所以接下来剩余的n-2本书就又回到了初始的状态,对这n-2本书进行错排;
结合开始的n-1中情况,所以这种情况种数为(n-1)*dp[n-2].
2:不放在m位置上,那就相当于原本这本书要放在M位置上,现在不放了,并且其他的n-2本书也不放在原来的位置上,那么现在就有n-1本书不能放在原来的位置上,所以这种情况就是dp[n-1],结合开始的情况,就是(n-1)*dp[n-1].
总:结合前面的两种情况,那么总的情况就有:(n-1)*(dp[n-2] + dp[n-1]).
这里有一道例题供大家参考
转眼毕业了,曾经朝夕相处的同学们不得不都各奔东西,大家都去了不同的城市开始新的生活。在各自城市居住了一段时间后,他们都感到了一些厌倦,想去看看其他人的生活究竟如何,于是他们都选择到另一个同学所在城市去旅游,并且希望旅游的城市各不相同,他们想知道有多少种不同的方案,可是数量实在太多了,他们无法计算出来,你能帮助他们吗。
输入格式
一个正整数 n(n\le 20)n(n≤20),表示人数。
输出格式
一个数,表示有多少不同的方案。
输出时每行末尾的多余空格,不影响答案正确性
样例输入复制
3
样例输出复制
2
这其实也就是进行错排操作,代码如下:
//@author:hairu,wu
//@from:ahut
#include<iostream>
using namespace std;
typedef long long ll;
int main(){
int n;
cin >> n;
ll dp[100];
dp[0]=0;
dp[1]=0;
dp[2]=1;
for(int i=3;i<=n;i++){
dp[i]=(i-1)*(dp[i-2]+dp[i-1]);
}
cout<<dp[n]<<endl;
return 0;
}