題意:
有n乘m 的棋盤,現在有1乘2的方塊和2乘1大小的方塊,問有多少種不同的組合方式。
思路:
這道題有很多種方法可以做,輪廓線dp和插頭dp、狀態壓縮都行,先講一下狀態壓縮方法。
大神的題解:
兩種方塊方的方式有橫豎兩種方式可以放置,狀態壓縮一般壓縮到二進位制中用01表示,規定01
為豎著放置,11為橫著放置,那麼,在轉移的過程中必須要知道的是上一行的狀態比如上乙個中第k個位置是0那麼當前行第k位置必須是1,所以說當把兩行所有對應的關係都計算出了之後便可以枚舉行依次加法即可得出答案。
那麼問題是如何求出這麼多個對應關係,先找出規律,把不滿足的情況刪除,i-1行第k位置是0,那麼i行第k位置是1,不是1便刪除,尋找第k位置的時候是從0列開始當第0列是1的時候第1列也是1,每次保證都是與前一列無關專注於下一列的要求即可。
#include
#include
#include
#include
using
namespace
std;
const
int maxn = 15;
int n,m,w;
long
long dp[maxn][1
void get_path()
}else
else
else
if((j&(1
<<(k-1))) == 0 && (j&(1}}
}int main()
}printf("%i64d\n",dp[n][(1
<1]);
}return
0;}
上一種狀態壓縮的方式很暴力,很容易超時。。。
思考上乙個方法發現是對前一行的每一種狀態都進行了列舉,兩重迴圈的暴力列舉使得數量級急劇增加,思考更好的方式!
當前位不放,則前行的當前位必定為1才能相容且後行為0:c=c+1,[(pre<<1)
|1,n
ow<<1]
當前位上方,則前行的當前位必定為0才能相容且後行為1:c=c+1,[(
pre<<1)
,(no
w<<1)
|1]
當前位右方,則前行的當前2位必定為1才能相容且後行當前2位為1:c=c+2,[(
pre<<2)
|3,(
now<<2)
|3]
且要注意到:如果執行以上操作而使得c==m,則表明生成了乙個相容對。如果c>m,則表明生成了一非法的長度越界相容對,要拋棄。
#include
#include
#include
#include
using
namespace
std;
const
int maxn = 15;
int n,m,w;
int path[500000][2];
long
long dp[maxn][1
dfs((pre<<1)|1,now<<1,c+1);
dfs(pre<<1,(now<<1)|1,c+1);
dfs((pre<<2)|3,(now<<2)|3,c+2);
}int main()
}printf("%i64d\n",dp[n][(1
<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...