骨牌平鋪問題

2021-07-15 07:40:12 字數 3683 閱讀 6309

有乙個n*m的棋盤,現在用1*2的骨牌去覆蓋,問有多少種不同方法可以將這個棋盤全部覆蓋。

1、狀態壓縮dp

列舉相鄰兩行的狀態進行匹配轉移 複雜度o( n * (2^m)^2 )

poj 2663:

#include // poj 2663.cpp

#include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std;

#define rep(i,j,k) for (int i=j;i<=k;i++)

#define rrep(i,j,k) for (int i=j;i>=k;i--)

#define clean(x,y) memset(x,y,sizeof(x))

#define ll long long

#define ull unsigned long long

#define inf 0x7fffffff

#define mod %100000007

int n;

ll dp[35][8];

bool fit(int x1 , int x2 , int uplim)

int main()

if ( n & 1 )

clean(dp,0);

dp[1][0] = dp[1][3] = dp[1][6] = 1;

int uplim = 1<<3;

rep(i,2,n)

rep(j,0,uplim-1)

rep(k,0,uplim-1)

if( fit(j,k,uplim-1) ) dp[i][j]+=dp[i-1][k];

cout<

#include //hiho 1161.cpp

#include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std;

#define rep(i,j,k) for (int i=j;i<=k;i++)

#define rrep(i,j,k) for (int i=j;i>=k;i--)

#define clean(x,y) memset(x,y,sizeof(x))

#define ll long long

#define ull unsigned long long

#define inf 0x7fffffff

#define mod 12357

int uplim;

int n,k;

struct node

void zhuanyi()

void dfs( int x , int y , int col ) //構造上一行狀態為x,當前行狀態為y x->y的轉移矩陣

dfs( x<<1|1 , y<<1 , col + 1 ); //第col列不放,所以上一行已經被填充過了,而當前行還是空的

dfs( x<<1 , y<<1|1 , col + 1 );//col列豎著放,上一行肯定沒有被填充,而放過之後當前行會被填充

if ( col + 2 <= k ) dfs( x<<2|3 , y<<2|3 , col + 2 );//在當前行的col列和col+1列橫著放

}};node multi( node &x , node &y ) //矩陣乘法

return ans;

}int main()

cout<

3、掃瞄線

複雜度 o( n*m*2^m )

uva 11270

#include //uva 11270.cpp

#include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std;

#define rep(i,j,k) for (int i=j;i<=k;i++)

#define rrep(i,j,k) for (int i=j;i>=k;i--)

#define clean(x,y) memset(x,y,sizeof(x))

#define ll long long

#define ull unsigned long long

#define inf 0x7fffffff

#define mod %100000007

const int maxn = 13;

ll dp[2][1<1 && !( k & 1<<(m-1) ) ) //豎著放

update( k , k<<1|1 , cur );

if ( j > 1 && ( k & 1<<(m-1) ) && !( k & 1 ) ) //橫著放

update( k , (k<<1)^(uplim+1)^3 , cur );}}

printf("%lld\n",dp[cur][uplim]);

}int main()

return 0;

}3、狀態壓縮轉移

列舉相鄰兩行的狀態進行匹配轉移 複雜度o( n * (2^m)^2 )

poj 2663

#include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std;

#define rep(i,j,k) for (int i=j;i<=k;i++)

#define rrep(i,j,k) for (int i=j;i>=k;i--)

#define clean(x,y) memset(x,y,sizeof(x))

#define ll long long

#define ull unsigned long long

#define inf 0x7fffffff

#define mod %100000007

int n;

ll dp[35][8];

bool fit(int x1 , int x2 , int uplim)

int main()

if ( n & 1 )

clean(dp,0);

dp[1][0] = dp[1][3] = dp[1][6] = 1;

int uplim = 1<<3;

rep(i,2,n)

rep(j,0,uplim-1)

rep(k,0,uplim-1)

if( fit(j,k,uplim-1) ) dp[i][j]+=dp[i-1][k];

cout<

骨牌覆蓋問題

骨牌覆蓋問題,就是用 1x2 大小的骨牌,鋪設乙個給定大小的乙個矩形區域,要求必須鋪滿,且不可以超出邊界。問總的鋪設方案數字多少?這一類問題就是骨牌覆蓋問題。不同規模的資料有不同的方法。下面來看看最簡單的 2 n 區域裡面的鋪設方法數。n 0,一種 n 1 為一種 n 2,兩種 n 3,5種 較為容...

骨牌覆蓋問題

骨牌覆蓋問題 用1 2骨牌完美覆蓋n m棋盤,求方案數 如果骨牌橫著放,只能兩個橫著的骨牌摞在一起 如果豎著放,恰好佔一列 所以dp i dp i 1 dp i 2 即斐波那契數列 可以想到乙個遞推式 f n a2 f n 2 a4 f n 4 a6 f n 6 an f 0 ai i是偶數 是未知...

骨牌組成矩形問題

演算法 遞推 數學綜合 題目大意 有t資料,給定乙個2 n的矩陣,只能利用1 2和2 2的骨牌,讓你去組成2 n的矩陣,問有多少種組成方法。分析 從題目大意上不難看出,本題是一道遞推題目,由前面的組成方案可以推得後面的組成方案,具體推法如下 1 當前的2 n的矩陣可以拆分成2 n 1 1 2的或者是...