本题讨论的是每一行的矩形的摆放,而一开始因为纠结于将一个矩形用一个二进制表示,但矩形摆放的方式不同每一行的数位也就不同所以思路就此卡住了。。。。。。
但我们从矩形的摆放方式将其定义成1和0,并且每一个边长为1的小格都有一个0或1,这样就保证了每一层二进制位数的相同,那么这样写的状态转移方程是什么样的呢?
我们从某一层来看,某一层可以如何摆放其实取决于上一层的摆放情况。
我们设、1:表示竖着摆放的积木
0:表示横着摆放的积木。
对于某一层来说如果上一层是1的话下一层一定是0,因为上一层是竖着放的那么下一层是不能放东西的,直接用0表示也可以,毕竟横着放本身对下一层也没有影响。
如果上一层是0的话,这一层就任意,但是要注意除上一层是1的情况外这一层的0必须成对出现,即连续的0必须是偶数个。对于上一层是1的情况用或运算就可以将其去除。
那么最后要的是一个完整的矩形,所以最后一层一定全部都是横着放的。
状态转移方程:dp[cur][i] += dp[last][i-1];
#include <bits/stdc++.h> using namespace std; #define int long long const int maxn = 12; int h, w; int dp[1<<11][maxn]; bool check(int x) { int ww = w; int cnt = 0; while (ww--) { if (x&1) { if (cnt&1) return false; cnt = 0; } else cnt++; x = x>>1; } if (cnt&1) return false; return true; } signed main() { while (cin>>h>>w) { memset(dp, 0, sizeof(dp)); if (h==0&&w==0) break; dp[0][0] = 1; int len = (1<<w)-1; for (int i=1;i<=h;i++) { //遍历当前层的所有可能性 for (int cur=0;cur<=len;cur++) { //对最后一行的特判 if (cur&&(i==h)) continue; //遍历上一层的所有可能性 for (int last=0;last<=len;last++) { if (cur&last) continue; if (check(cur|last)) { dp[cur][i] += dp[last][i-1]; // cout<<dp[cur][i]<<endl; } } } } cout<<dp[0][h]<<endl; } return 0; }