洛谷P1990 覆蓋牆壁:怎樣解決遞推問題?

題目見

P1990

遞推問題的關鍵是要找到前一次和後一次之間的關係。
只要找到這個關係(或者說,列出表達式),那麼問題已經得到了解決。

這個題目怎樣找到前一次呢?

  • 首先 確定一列i。集中目光在這一列上。

  • 由於有兩種不同的磚,我們要確定上一塊磚的類型

    • 條形磚
    • L形磚
  • 條形磚可以有不同的方向:

    • 條形磚可以豎着放:那麼減掉一塊磚,對應的情況就是i-1列的完全情況。
    • 條形磚可以橫着放:只能放兩塊才能對應到上一個完全情況即i-2
  • L形磚:

    • 如果將底邊對向大端,那麼會出現一個缺格。這個缺格將導致無法彌補的缺陷。即先前的完全情況加上這一塊磚後無論如何不能填滿。

    如圖綠色爲完全區域,紅色爲本次操作的磚塊。白色爲缺陷。

    • 所以L形磚只能將底邊朝向完全區。但這很快導致了新的問題。需要維護一種新的完全區域。即半滿型。圖示表現了我們的需求:

在這裏插入圖片描述

現在我們就來推導這個遞推關係:
我們在先前的全滿的基礎上可以加L形磚,與這個半滿的尾端兩相對應補成完整的一個2*3矩形,即可得到一個這個半滿數組的一個來源f(i-1)*1。但還有加條形磚的情況,且只能如圖放置:
在這裏插入圖片描述
我們又找到一個來源,即g(i-1)*1

  • 所以我們又得出了關於新數組的遞推式:
g(i) = g(i-1) + f(i-1)

簡單地初始化如下:

#define N 1000000 + 10
int f[N] = {1, 1}, g[N] = {0, 1};

主函數如下:

int main()
{
    int n, mod = 10000;
    cin >> n;
    for (int i = 2; i <= n; i++)
    {
        f[i] = (f[i-1] + f[i-2] + 2 * g[i-2]) % mod;
        g[i] = (g[i-1] + f[i-1]) % mod;
    }
    cout << f[n];
    return 0;
}

總結:
遞推問題要找到每一步的所有可能情況,然後求解來源。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章