多公尺諾骨牌問題,狀態壓縮dp

2021-08-25 02:57:53 字數 1766 閱讀 7770

**

題目描述:用1*2 的矩形通過組合拼成大矩形,求拼成指定的大矩形有幾種拼法。

首先 我們先求用1*2 的矩形拼成 n*m的矩形有多少種拼法

當n*m為奇數時,一定是不會拼出來的,因為想要拼出來就需要整數倍的小矩形數目。

為了加速演算法,要把m,n中小的那個當做列

分兩個步驟:1) 先求出相鄰兩行的轉化關係 

2) 通過相鄰兩行的轉化關係算出經過n次轉化有幾種方法能拼成n*m的矩陣

1) 狀態標記 橫放和豎放的下乙個均為1,豎放的上乙個和不放置為0 ,每行可以轉化為1個2進製數。當這一行訪問結束時,就會得到上一行狀態,和該行狀態,因為所有情況都是我們設定的,所以pre狀態一定會轉化為now狀態

對於每乙個位置,我們有三種放置方法:1. 豎直放置2. 水平放置3. 不放置

d為當前列號 ,初始化d, now, pre都為0。now為當前行,pre為當前行的上一行

1. d = d + 1, now <

2. d = d + 2, now <

3. d = d + 1, now <

因為轉移狀態有很多種,所以用dfs去列舉各種可行的狀態。

下面是dfs實現:

2) 求出來相鄰兩行之間的狀態轉化,下面就要求經過n次轉化後最後狀態為(1<

當n很大的時候,就不能用上述的方法算了,這個時候矩陣的優勢就體現出來了

同樣是求經過n次轉化,從初始態到終態有幾種轉化法

建立矩陣的方法很簡單,矩陣的大小為(1<1、poj2411 題意:給定乙個長寬小於等於11的矩形,問用1×2的小矩形填滿,有多少種方法。

#include #include #include #define ll long long

using namespace std;

const int maxn=13;

int w,h,tan;

ll dp[13][2100];//1<<11

int path[14000][2];//11*(1<<11)

void dfs(int l,int now,int pre)

dfs(l+2,(now<<2)|3,(pre<<2)|3);

dfs(l+1,(now<<1)|1,pre<<1);

dfs(l+1,now<<1,(pre<<1)|1);

}int main()

;mat dat;

int n,mod;

void dfs(int l,int now,int pre)

dfs(l+1,(now<<1)|1,(pre<<1));

dfs(l+1,(now<<1),(pre<<1)|1);

dfs(l+2,(now<<2)|3,(pre<<2)|3);

}mat mul(mat a,mat b)}}

} }return c;

}mat expo(mat a,int k)

if(k==0)return e;

while(k)

return e;

}int main()

mat ans=expo(dat,n);

printf("%lld\n",ans.at[15][15]);

} return 0;

}

多公尺諾骨牌

100張多公尺諾骨牌整齊地排成一列,按順序編號為1 2 3 4 99 100。第一次拿走所有的奇數字置上的骨牌,第二次再從剩餘的骨牌中拿走所有奇數字置上的骨牌,依次類推,請問最後剩下的一張骨牌的編號是多少 a.48 b.50 c.52 d.64 正確答案 d.答對了嗎?答對了嗎?答對了嗎?第一次拿走...

多公尺諾骨牌

現有n塊 多公尺諾骨牌 s1,s2,s3,sn水平放成一排,每次骨牌si包含左右兩個部分,每個部分賦予乙個非負整數值,如下圖所示為包含6塊骨牌的序列.骨牌可做180度旋轉,使得原來在左邊的值變到右邊,而原來右邊的值移到左邊,假設不論si如何旋轉,l i 總是儲存si左邊的值,r i 總是儲存si右邊...

多公尺諾骨牌

在課堂上,我們分析了棋盤覆蓋問題,同學們也看了我的程式執行的情況,今天我們來看一下另外乙個覆蓋問題。今天的問題是這樣的 用n個2x1的矩形 這種矩形我們以後稱之為骨牌或多公尺諾 覆蓋2xn的棋盤,有多少種不同的覆蓋法?input 本問題有多組測試資料,對於每一組測試資料,輸入只有一行n 意義如上所述...