2011-06-01 22:00:05Morris

d624. 燈泡問題

http://zerojudge.tw/ShowProblem?problemid=d624

內容 :

跨年夜你去了正妹小璇的家跨年(注意:只有跨年)
為了增加一點浪漫情調

你想讓燈泡開開關關的,以為這樣感覺會很有feel

但是燈泡連續暗太久小璇會感到害怕並且從此不理你

小璇能忍受燈泡連續n單位的時間是暗的,而總時間是m單位時間。

你想寫一個程式,給定n和m的值,算出有幾種不同的明暗排列方式,每一種排列方式之中都不會出現暗超過連續 n單位時間的區段。

輸入說明 :

有兩個數字n和m以一個空白分開,其中 1<=n<=15,1<=m<=90。

輸出說明 :

對於每一筆輸入請輸出一個數字,代表排列方式的總數。每個答案保證不會超過264-1,所以你不必考

慮有大數的情況會發生。

範例輸入 :help

2 4

範例輸出 :

13

提示 :

範例輸出說明:

亮用○表示,暗用●表示,則有下面13種方式。

 1 ○○○○    2 ●○○○    3 ●○●●
 4 ●●○●    5 ○○○●    6 ○○●●
 7 ○●○●    8 ○●●○    9 ●○○●
10 ●○●○   11 ●●○○   12 ○○●○
13 ○●○○

以下是不合題目敘述的方式。

 1 ●●●●    2 ○●●●    3 ●●●○

出處 :

TIOJ (管理:david942j)

作法 : DP
我不會導公式,所以別 ... 請你提供
DP[m][n][p] m : 總共m個燈泡, n : 連續暗的最大剛好n個, p : 在結尾有連續 p 個是暗的
定義 :
[1][0][0] = 1, [1][1][1] = 1;
1 . n = 0, p =0 : DP[m][0][0] = 1; (基本的)
2.  p = 0 : DP[m][n][0] = DP[m-1][n][0~n] (在結尾補亮的)
3.  n = p : DP[m][n][n] = DP[m-1][0~m][n-1](在結尾補暗的)
4.  p = 1 : DP[m][n][1] = DP[m-1][n][0](在結尾補暗的)
5.  others : DP[m][n][p] = DP[m-1][n][p-1](在結尾補暗的)

Ans = DP[m][0~n][0~n]

/**********************************************************************************/
/*  Problem: d624 "燈泡問題" from TIOJ                                        */
/*  Language: C                                                                   */
/*  Result: AC (4ms, 1306KB) on ZeroJudge                                         */
/*  Author: morris1028 at 2011-06-01 21:39:50                                     */
/**********************************************************************************/


#include<stdio.h>
main() {
    int n, m, p, a, b;
    long long DP[91][91][16] = {};
    DP[1][0][0] = 1, DP[1][1][1] = 1;
    for(m = 2; m <= 90; m++)
        for(n = 0; n <= m; n++)
            for(p = 0; p <= 15 && p <= n; p++) {
                if(n == 0 && p == 0)
                    DP[m][0][0] = 1;
                else if(p == 0) {
                    for(a = 0; a <= n && a <= 15; a++)
                        DP[m][n][0] += DP[m-1][n][a];
                }
                else if(n == p) {
                    for(a = 0; a <= n; a++)
                        DP[m][n][n] += DP[m-1][a][n-1];
                }
                else if(p == 1)
                    DP[m][n][1] = DP[m-1][n][0];
                else
                    DP[m][n][p] = DP[m-1][n][p-1];
        }
    while(scanf("%d %d", &n, &m) == 2) {
        long long Ans = 0;
        for(a = 0; a <= n; a++)
            for(b = 0; b <= n; b++)
                Ans += DP[m][a][b];
        printf("%lld\n", Ans);
    }
    return 0;
}