1. 程式人生 > >hdu_2048 錯排問題

hdu_2048 錯排問題

pac scanf pre sin 寫法 就是 ID ++ size

錯排問題本質上就是一個動態規劃問題,其狀態轉移方程為:

記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; }

hdu_2048 錯排問題