題目:
給你nm(1<=n,m<=11)的方格矩陣,要求用12的多公尺諾骨牌去填充,問有多少種填充方法。
分析:
首先我們定義如下這種填充表示方式:如果乙個骨牌是橫著放的,那麼它所在的兩個方格都填充1.如果它是豎著放的,那麼它所在的兩個格仔中,上面的那個填0,下面的這個填1.如下圖所示:
該矩陣的骨牌擺放方法和該矩陣的二進位制表示法是一一對應的。對於任意連續的兩行i-1和i行來說,第i-1行的二進位制表示和i行的二進位制表示有乙個相容的關係。
用pre表示前一行的二進位制形式,now表示後一行的二進位制形式,c表示當前操作的列號。c,pre,now初值都為0.由於是
從左邊位模擬到最右邊的位,所以對應3種操作的結果為:
上面的過程就是模擬出所有的相鄰兩行可以以什麼樣的(相互相容的)樣式放在兩行中
//path[i][0]---表示第i種兩行相互相容的方式中前一行值是多少(11111111這種形式轉化為了十進位制了)
//path[i][1]--表示第i中兩行相互相容的方式中當前行的二進位制形式對應的值是多少,
void get(int c,int pre,int now)//c表示當前列號,得到具有m列的矩陣的所有對應相容方式存入path中
get(c+1,(pre<<1)|1,now<<1); //豎著放
get(c+1,(pre<<1),(now<<1)|1); //不放
get(c+2,(pre<<2)|3,(now<<2)|3); //橫著放,
}
d[i][num]----表示第i行對應二進位制形式值為num時,有多少種方法,
然後就是遍歷,
d[0][(1總的**:
#include#include#includeusing namespace std;
int n,m,w;
const int maxn =15;
long long d[maxn][1<<15];
int path[5000000][2];//path[10][0]表示第11種(從0計數)相容方式的前一行二進位制形式對應的的值
//path[10][1]表示第11種(從0計數)相容方式的後一行二進位制形式對應的的值
//一共可能有(1<<11)*(1<<11)種相容方式
void get(int c,int pre,int now)//得到具有m列的矩陣的所有對應相容方式存入path中
get(c+1,(pre<<1)|1,now<<1);
get(c+1,(pre<<1),(now<<1)|1);
get(c+2,(pre<<2)|3,(now<<2)|3);
} int main()
printf("%i64d\n",d[n][(1<
}return 0;
}
poj 2411 狀態壓縮DP
用乙個vector容器來記錄當前狀態下有哪些狀態可以繼承。比如說vec i 裡面的所有的數代表當第一行為i狀態時,第二行的可行狀態。對於狀態i,其二進位制中0的地方表示為當前狀態為豎著的木板的下半部分。其二進位制中1的地方表示為當前狀態為橫著的木板或者豎著的木板的上半部分。include inclu...
POJ 2411 狀態壓縮DP
題目大意 給乙個h w的方格,現給出1 2和2 1的兩種小方塊,求出把h w方格鋪滿的不同方案數 1 h,w 11 分析 首先能想到的是如果h w為奇數,那麼肯定不能放滿,結果為0 如何表示狀態 從題目看資料很小,那麼很容易想到用二進位制來表示狀態,0表示當前方格沒放,1表示放了 這裡用dp r c...
poj2411 狀態壓縮dp
一道經典狀態壓縮dp題目。題意很明確,讓用1 2或2 1的小方格鋪滿地板。根據狀態壓縮的慣用思路,當前行的地板狀態是由當前行和上一行共同決定的,肯定要用乙個二進位制數表示一行的狀態,然後再用狀態轉移方程轉移求解。這道題可以這麼想,對於每個狀態,如果是1 2的橫著放,將兩個位置都標記為1,如果是2 1...