題目傳送門:點我
NowCoder每天要給很多人發郵件。有一天他發現發錯了郵件,把發給A的郵件發給了B,把發給B的郵件發給了A。於是他就思考,要給n個人發郵件,在每個人僅收到1封郵件的情況下,有多少種情況是所有人都收到了錯誤的郵件?
即沒有人收到屬於自己的郵件。
結合我們的做題步驟:
1).定義一個能夠清楚描述最優子問題的數組(明確數組描述的含義)。
2).找出數組元素之間的關係式(狀態轉移方程)
3).找出初始值
code:
這道題的狀態轉移方程還是不容易找出的(南首- - )。
A B C ... N (郵件)
a b c ... n(郵箱)
假設A放入b
1)如果 B放入a 那麼剩下n-1個的郵件或郵箱和abAB都沒有了關係記爲dp[i] = dp[i-2]
2)如果B沒有放入a 那有如下狀態:
B C ... N (郵件)
a c ... n(郵箱)
dp[i] = dp[i-1]
綜合1)2)並且,還有其他情況 A裝入c,裝入i的i-1種錯誤之下,同樣都有dp[i-1]+dp[i-2]種錯裝法,因此
dp[i] = (i-1) * (dp[i-1] + dp[i-2])
public class LTDP {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNextInt()) {
int b = sc.nextInt();
System.out.println(ErrNum(b));
}
}
private static long ErrNum(int num) {
long [] dp = new long[num + 1]; // dp[i]表示第i個郵件以及之前錯裝的種類數量
dp[1] = 0; dp[2] = 1;
if(num == 2 ){
return dp[2];
}
for(int i = 3 ;i <= num;i++){
dp[i] = (i - 1) *(dp[i-1] + dp[i-2]);// 轉移方程 :如何得出如上述解釋
}
return dp[num];
}
}