有1個n*m的盤子,要裝2*1的蛋糕,問有多少種方法?(結果對1000000007取餘,其中2≤n≤1000,3≤m≤5)
最簡單的例子如下:
下面我們來分析:
這個題目類屬於狀態壓縮dp,對於狀態壓縮dp,其實最簡單的理解就是把狀態用位元位的形式表示出來,我們會在下面用例子來說明。
假如現在我們在鋪磚 位置(i,j), 並且假設之前的位置已經鋪設好的了,在這個位置,我們的選擇:
1. 不用鋪磚了,可能在(i-1, j)的時刻已經被豎著鋪上了,然後考慮的是(i, j+1)
2. 橫鋪磚,將(i, j+1)也鋪上了,然後考慮的是(i, j+2)。
3. 豎著鋪磚,(將i,j)和(i+1,j)鋪上乙個豎立的轉頭。
所以我們如下翻譯我們的選擇,在位置(i, j) 如果我們選擇橫著貼磚,那麼將(i, j), (i, j+1)都填寫成1,如果豎著貼磚,我們將(i,j)填寫成0,將(i+1, j)填寫成1.
問題1:為什麼要這麼計數呢,我覺得應該這樣理解:
1. 在橫著貼磚的時候,(i, j), (i, j+1) 都是1,這個值其實對下一行如何選擇沒有影響。
2. 豎著貼磚的第二個,我們也選擇了1, 因為這個磚頭結束了,對下一行如何選擇依然沒有影響。
3. 而豎著的第乙個磚頭,這個磚頭是對下面有影響的,如果(i,j)是0,那麼(i+1,j)只有是1的情況下才能滿足條件。
即當設為1表示對下一行沒有任何影響了。
問題2:如何判斷當前狀態與上一行的狀態是否相容
其實我們在上面已經基本給出分析, 如果我們現在鋪設 (i,x) x這裡表示第i行,第x列
1. 如果值 i 行,j 在x位上的值是0, 那麼第 i-1行,j的值在x位上一定是1。因為不可能在同一列相鄰的位置鋪兩個豎著的 第乙個,如果滿足下一步測試的是(i, x+1), 否則直接返回不相容。
2. 如果值 i 行,j在x位置的值是1 .
那麼有可能有兩種情況:
1. (i-1, x)是0, 這個時候一定是豎著鋪設了,下一步檢測的是(i, x + 1)
2. (i-1, x) 是1, 如果是這樣的話,那麼(i,
x)一定是要選擇橫著鋪了,那麼(i,x+1)也一定是1,並且(i-1,x +
1)一定是1(如果是0,就是豎著鋪了),如果不滿足就返回不相容,滿足條件 就測試(i,x + 2)
對於第一行的相容性,我們要做一下特別的分析,在第一行中,要麼放0, 要麼放1。
加入當前測試的是 dp(0, j)的第 x的位元位,即第0行,x列
1. 如果x是1,那麼 x + 1 也一定是1,然後測試到 x + 2
2. 如果x是0, 那麼直接測試下乙個 x + 1
特別注意:這裡的判斷的(i,x)一定不是由(i,x-1)位橫著鋪磚過來的,否則直接x=x+2,就不會來判斷(i,x)位了。
問題3:為什麼可以使用動態規劃演算法來解決這個問題?
這就得從動態規劃的特性上去找:
(1)最優子結構
用f[i][j]表示第i行j狀態鋪磚塊的方案數,一定等於i-1行所有的能與狀態j相容的狀態k的方案的總和。
(2)重複子問題
求f[i][j]即第i行的每乙個狀態一定要用到第i-1行的各個狀態。
問題4:從狀態壓縮的特點來看,這個演算法適用的題目符合以下的條件:
1.解法需要儲存一定的狀態資料(表示一種狀態的乙個資料值)
,每個狀態資料通常情況下是可以通過二進位制來表示的。這就要求狀態資料的每個單元只有兩種狀態,比如說棋盤上的格仔,放棋子或者不放,或者是硬幣的正反兩面。這樣用 0 或者 1 來表示狀態資料的每個單元,而整個狀態資料就是乙個一串 0 和 1 組成的二進位制數。
2.解法需要將狀態資料實現為乙個基本資料型別,比如int,long等等,即所謂的狀態壓縮。狀態壓縮的目的一方面是縮小了資料儲存的空間,另一方面是在狀態對比和狀態整體處理時能夠提高效率。這樣就要求狀態資料中的單元個數不能太大,比如用
int 來表示乙個狀態的時候,狀態的單元個數不能超過 32(32 位的機器)。
//注:j&(1#define swap(a,b) a=b-a+(b=a)
#define false 0
#define true 1
int testfirstline(int j,int m){
int i=0;
while(i
參照:
一道演算法題
兩個燒杯,乙個放糖乙個放鹽,用勺子舀一勺糖到鹽,攪拌均勻,然後舀一勺混合 物會放糖的燒杯,問你兩個燒杯哪個雜質多?一樣多吧 對的 為啥?是不是因為 糖和鹽本來就是均勻的 因為,就算不攪拌均,你放一勺過去,那邊放一勺不含雜質的過來,那麼都是一勺雜之 如果攪拌均勻的話也是一樣 小依 21 45 32 也...
一道演算法題
1.上午主要做了對翻譯任務的劃分,下午把 翻譯完畢。2.明天要講的演算法題 對乙個集合,求出其連續元素組成的子集中,和最大的子集 我對這道題的理解是 1 若集合中最小值大於0,意味著所有的都大於0,則最大的子集和,為所有值加起來 2 若集合中最大值小於0,意味著所有的都小於0,則最大的子集和,為集合...
一道演算法題
include using namespace std const int size 5 int max sub array const int a,int n,int m int max matrix const int a size int row,int col,int subsize int...