有乙個n行m列的廣場,需要用1*2小磚鋪蓋,小磚之間互相不能重疊,問有多少種不同的鋪法?
題解設f[i
][j]
f[i][j]
f[i][j
]表示第i
ii行,狀態為j
jj的方案數。在狀態j
jj中,1
11表示豎著放長方形的上半部分。0
00表示其餘部分。
顯然上一排空缺的部分肯定是要豎著放置的。
就看剩下橫著的能不能連續的兩個兩個放置。
狀態轉移很顯然:f[i
][j]
=∑f[
i−1]
[k]f[i][j]=\sum f[i-1][k]
f[i][j
]=∑f
[i−1
][k]
關鍵在於我們應該如何選取合法的狀態。
**如下:
#include
#define int long long
using
namespace std;
const
int n =12;
int n, m;
int ok[
1<
, f[n][1
<
;signed
main
(void
) f[0]
[0]=
1;for(
int i=
1;i<=n;
++i)
for(
int j=
0;j<
;++j)
for(
int k=
0;k<
;++k)if(
(j & k)==0
&& ok[k|j]==1
) f[i]
[j]+
= f[i-1]
[k];
cout<< f[n][0
]<< endl;
return0;
}
給出n××m(1≤n、m≤9)的方格棋盤,用12 的矩形的骨牌和l 形的(22 的去掉乙個角)骨牌不重疊地覆蓋,求覆蓋滿的方案數。
題解這題比較玄乎,我們需要使用dfs來解決。
我們考慮當前行的狀態s1,和上一行的狀態s2的關係來轉移。顯然有f[i
][s1
]=∑f
[i−1
][s2
]f[i][s1]=\sum f[i-1][s2]
f[i][s
1]=∑
f[i−
1][s
2]問題還是轉移合法性。
我們在每一行轉移的時候,嘗試去列舉每一位,如果對右邊有影響,即如果要往右邊延伸的話用乙個變數標記,在下一次轉移的時候特判即可。
b1表示當前列是否被收到了影響,即是否已經被佔據了。是為1,否則為0.b2表示前一行。
注意前一行的狀態標記狀態要反著來,例如要對前一行填充,那麼轉移的狀態就是空的。
距離是這樣的。
**如下:
#include
#define int long long
using
namespace std;
const
int n =12;
int n, m, i;
int f[n][1
<
;void
dfs(
int k,
int s1,
int s2,
int b1,
int b2)
signed
main
(void
)
狀態壓縮dp入門 鋪磚問題
mondriaan s dream hardwood floor 第一道題目是只有一種磚,2x1可以橫著鋪,可以豎著鋪,問有多少種鋪法第二道是有兩種磚,一種是2x1的,一種是2x2的去掉乙個1x1的角也是問有多少中鋪法首先第一道我們用0 1來表示不鋪和鋪兩種狀態每一行用01字串表示狀態然後再轉化為乙...
狀態壓縮動態規劃
動態規劃的狀態有時候比較難,不容易表示出來,需要用一些編碼技術,把狀態壓縮的用簡單的方式表示出來。典型方式 當需要表示乙個集合有哪些元素時,往往利用2進製用乙個整數表示。一般有個資料 n 16 或者 n 32 這個很可能就是狀態dp的標誌,因為我們要用乙個int的二進位制來表示這些狀態。要注意好這些...
動態規劃 狀態壓縮
這個題目的題意很容易理解,在乙個n m的格仔裡,我們現在有兩種型別的磚塊,1 2和 2 1,問一共有多少種方案,可以將整個n m的空間都填滿。最簡單的例子就是下面的了 程式設計之美中題目 某年夏天,位於希格瑪大廈四層的微軟亞洲研究院對辦公樓的天井進行了一次大規模的裝修.原來的地板鋪有 n m 塊正方...