发邮件(错排问题dp)

发邮件(错排问题)

题目链接
题目描述
NowCoder每天要给很多人发邮件。有一天他发现发错了邮件,把发给A的邮件发给了B,把发给B的邮件发给了A。于是他就思考,要给n个人发邮件,在每个人仅收到1封邮件的情况下,有多少种情况是所有人都收到了错误的邮件?
即没有人收到属于自己的邮件

输入:
2
3
输出:
1
2


思路

  1. DFS方法超时
int N=0;
void dfs(int,int);
int book[100]={0};
int main()
{
   int n;
   scanf("%d",&n);
   dfs(0,n);
   printf("%d",N);
}
void dfs(int num,int n)
{
   if(num==n) N++;
   else
   {
       int i;
       for(i=0;i<n;i++)
           if(book[i]==0&&i!=num)
           {
               book[i]=1;
               dfs(step+1,n);
               book[i]=0;
           }
   }
}
  1. 分为两种情况:
    第一种:前n-1种均是错位的,将第n个和前n-1个任意一个交换都可以 D(n-1)种放法,由于 D(n-1)的每种放法都可以衍生出和第n个邮件交换的n-1种放法,所以一共是(n-1)*D(n-1)种放法
    第二种:前n-1种,有n-2种均是错位的,有1个正确的(这个正确的可以是在前n-1个中的任意位置),将这个正确的和第n个交换 ,变成错位,而除开正确的和第n个外剩下的n-2个有D(n-2)种放法,所以一共是(n-1)*D(n-2)种放法

代码如下:

// write your code here cpp
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
   int n=0;
   vector<long long> dp(21,0);
   dp[2]=1;
   for(int i=3;i<=20;i++)
   {
       dp[i]=(i-1)*(dp[i-1]+dp[i-2]);
   }
   while(cin>>n)
   {
       cout<<dp[n]<<endl;
   }
   return 0;
}

`

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值