本题讨论的是每一行的矩形的摆放,而一开始因为纠结于将一个矩形用一个二进制表示,但矩形摆放的方式不同每一行的数位也就不同所以思路就此卡住了。。。。。。
但我们从矩形的摆放方式将其定义成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;
}

京公网安备 11010502036488号