hdu_2048 错排问题

 错排问题本质上就是一个动态规划问题,其状态转移方程为:

记d[n]为n个人错排情况的总数。

那么策略可以描述为:分析第n个人错排的可能情况:

1)前n-1个人满足错排的情况,那么第n个人加入后还要错排意味着第n个人与前n-1个人里的任意一个交换字条(共有n-1种交换法)

2)若前n-1个人并不满足错排,但加入第n个人后满足错排。这必然意味着第n个人加入后与前n-1中的某个人交换字条后才满足n个人错排。而又因为原本前n-1人不满足错排,那么前n-1个人中至少有一个人手上的字条是匹配的,那么第n个人就只能与匹配者交换字条。此时可以证明前n-1人中字条匹配者人数不能大于1,可以反证(如果有两人字条匹配,那么在第n个人交换后必然还有一个人字条匹配,不满足)

tip:

printf()输出百分号的时候,有的oj上必须写成%%,有的可以写成%。严格点的话,还是采用第一种写法稳妥。

ac代码如下:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring> 
using namespace std;
//错排思想 
long long d[30];
long long f(int n){
    if(d[n]!=-1){
        return d[n];
    }
    else{
        d[n]=(n-1)*(f(n-1)+f(n-2));
        return d[n];
    }
}
int main(void){
    memset(d,-1,sizeof(d));
    d[1]=0;d[2]=1;
    f(20);
    int c;
    scanf("%d",&c);
    while(c--){
        
    int n;
    scanf("%d",&n);
    long long cnt1=d[n];
    long long cnt2=1;
    for(int i=1;i<=n;i++){
        cnt2*=i ;
    }
    double ans=double(cnt1)/double(cnt2);
    printf("%.2lf%%\n",ans*100);
    //printf("%.2lf%\n",ans*100); //这样写就是wronganser 
        
    }

    return 0;
}

 

posted @ 2018-04-22 17:12  KYSpring  阅读(105)  评论(0编辑  收藏  举报