luogu p1990 覆蓋牆壁

2021-10-19 04:22:06 字數 3346 閱讀 4595

傳送門

你有乙個長為n寬為2的牆壁,給你兩種磚頭:乙個長2寬1,另乙個是l型覆蓋3個單元的磚頭。如下圖:

0 0 

0 00

磚頭可以旋轉,兩種磚頭可以無限制提供。你的任務是計算用這兩種來覆蓋n*2的牆壁的覆蓋方法。例如乙個2*3的牆可以有5種覆蓋方法,如下:

012 002 011 001 011 

012 112 022 011 001

注意可以使用兩種磚頭混合起來覆蓋,如2*4的牆可以這樣覆蓋:

0112 

0012

給定n,要求計算2*n的牆壁的覆蓋方法。由於結果很大,所以只要求輸出最後4位。例如2*13的覆蓋方法為13465,只需輸出3465即可。如果答案少於4位,就直接輸出就可以,不用加0,如n=3,時輸出5。

乙個整數n(1<=n<=1000000),表示牆壁的長。

輸出覆蓋方法的最後4位,如果不足4位就輸出整個答案。

13
3465
此題不用多說,動態規劃。但是這道題還是比較難講的,參考了一下題解才想出來一種比較易懂的講解?qaq233

設\(f_i\)為\(2\times i\)尺寸牆壁的恰好覆蓋方法。我們規定,\(f_0 = 1\)!!

來看\(n = 4\)的情況⑧,現在乙個都沒填充:

0000

0000

首先不考慮l形瓷磚。

如果瓷磚的最後兩格橫著鋪上了一形瓷磚,也就是這樣:

0001

0001

此時的方法數就是除去最後一列的子問題,也就是\(f_\)。

還有一種情況是瓷磚的最後四個豎著鋪上了一形瓷磚,也就是這樣:

0011

0022

注意哈是橫著鋪。豎著鋪的情況已經相當於第一種了。方法數是除去最後兩列的子問題,也就是\(f_\)。

答案就是兩種情況的綜合,也就是\(f_i = f_ + f_\)。

現在一字型瓷磚已經被我們討論完了,再來討論l形瓷磚。

此時再設乙個陣列,設\(g_i\)為既要覆蓋上\(2\times i\)尺寸牆壁,也要恰好多出一塊的覆蓋方法。規定\(g_0 = 0\)哦!

先在最後鋪乙個:

0001

0011

然後反向思維,不看鋪上的瓷磚,看空地。此時先補上前\(n - 2\)列的牆壁,然後再補多出的乙個。也就是說,這種情況的方案數是\(g_\)。

但是l形瓷磚可以反過來使用,也就是這樣:

0011

0001

此時的方案數仍然是\(g_\),所以實際上我們要統計兩次\(g_\)。

但是\(g\)陣列我們怎麼進行乙個維護呢?首先對於突出乙個方塊的,我們有兩種方法覆蓋。

第一種:再補乙個l,補成長方形:

0221

0211

當然

0211

0221

也是一樣的道理。

此時的方法數顯然就是\(f_\)辣。

第二種:繼續補長方形,仍然多出一塊

0221

0011

雖然這看著非常難受,強迫症甚至可以為此砸掉電腦,但是這種情況完全有可能啊!(哭)

這種情況下仍然還需要\(g\)陣列,不過相當於又填補了一列(雖然剛剛實際上是填補了乙個橫向的,但是把剛剛少的那一塊填上了兩塊,現在又多出了一塊,整體還是多了一列的,自己看看圖就知道了)。

這種情況的方案數是\(g_\)。

也就是說,\(g_ = f_ + g_\),也就等同於\(g_n = f_ + g_\)。

總結:\[\begin f_n = f_ + f_ + 2 \times g_ \\ g_n = f_ + g_ \end \]

這是兩個陣列的遞推式結果。其實本題到這裡本應該結束的,但是我們難道就不能壓成乙個陣列了嗎?

看\(g_n\)的遞推式。

\[g_n = f_ + g_\\ g_n = f_ + f_ + g_\\ g_n = f_ + f_ + f_ + \ldots + f_1 + f_0\\ g_n = \sum_ ^ f_i = \sum_ ^ + 1 \]

原式等同於:

\[f_n = f_ + f_ + 2 \times \sum_ ^ f_i + 2 \]

然後讓我施展一點魔法……讓\(n \rightarrow n - 1\)

這樣就可以得到:

\[f_ = f_ + f_ + 2\times \sum_ ^ f_i + 2 \]

對比這兩個式子:

\[f_n = f_ + f_ + 2 \times \sum_ ^ f_i + 2 \\ f_ = f_ + f_ + 2\times \sum_ ^ f_i + 2 \]

上式減下式,得到:

\[f_n - f_ = f_ + f_ + 2 \times \sum_ ^ f_i + 2 - (f_ + f_ + 2\times \sum_ ^ f_i + 2) \]

將等號右邊的式子整理一下,

\[f_n - f_ = f_ + f_ \]

然後把左邊的\(- f_\)移項,得到最終的遞推式:

\[f_n = 2 \times f_ + f_ \]

邊界條件:

\[f_1 = 1\\ f_2 = 2\\ f_3 = 5 \]

推出了式子以後,**就很好寫了。

/*

* @author: crab-in-the-northeast

* @date: 2020-04-14 22:11:54

* @last modified by: crab-in-the-northeast

* @last modified time: 2020-04-15 15:19:02

*/#include #include const int maxn = 1000005;

const int mod = 10000;

int dp[maxn] = ;

int main()

for(int i = 4; i <= n; i++)

dp[i] = (dp[i - 1] * 2 % mod + dp[i - 3] % mod) % mod;

std :: cout << dp[n] << std :: endl;

return 0;

}

ac 100:r32801187

洛谷 1990 覆蓋牆壁 遞推

題目描述 你有乙個長為n寬為2的牆壁,給你兩種磚頭 乙個長2寬1,另乙個是l型覆蓋3個單元的磚頭。如下圖 0 00 00 磚頭可以旋轉,兩種磚頭可以無限制提供。你的任務是計算用這兩種來覆蓋n2的牆壁的覆蓋方法。例如乙個23的牆可以有5種覆蓋方法,如下 012 002 011 001 011 012 ...

洛谷 P1990 覆蓋牆壁

你有乙個長為n寬為2的牆壁,給你兩種磚頭 乙個長2寬1,另乙個是l型覆蓋3個單元的磚頭。如下圖 0 0 0 00磚頭可以旋轉,兩種磚頭可以無限制提供。你的任務是計算用這兩種來覆蓋n 2的牆壁的覆蓋方法。例如乙個2 3的牆可以有5種覆蓋方法,如下 012 002 011 001 011 012 112...

洛谷 P1990 覆蓋牆壁

你有乙個長為n寬為2的牆壁,給你兩種磚頭 乙個長2寬1,另乙個是l型覆蓋3個單元的磚頭。如下圖 0 0 0 00 磚頭可以旋轉,兩種磚頭可以無限制提供。你的任務是計算用這兩種來覆蓋n 2的牆壁的覆蓋方法。例如乙個2 3的牆可以有5種覆蓋方法,如下 012 002 011 001 011 012 11...