傳送門
你有乙個長為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...