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