硬木地板 JDFZ1667

Description

举行计算机科学家盛宴的大厅的地板为M×N (1<=M<=9, 1<=N<=9)的矩形。现在必须要铺上硬木地板砖。可以使用的地板砖形状有两种:
1) 2×1的矩形砖
2) 2×2中去掉一个1×1的角形砖你需要计算用这些砖铺满地板共有多少种不同的方案。
注意:必须盖满,地板砖数量足够多,不能存在同时被多个板砖覆盖的部分。

Input

包含M和N。

Output

输出方案总数,如果不可能那么输出0 。

Sample Input

2 3

Sample Output

5
 
状压DP,搜索求现在状态能达到的所以状态
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath> 
using namespace std;
#define N (1<<11)+3
#define ll long long
ll f[10][N];
struct node
{
    int to,next;
}e[1<<20];
int head[N],cnt;
void add(int x,int y)
{
    e[cnt].to=y;
    e[cnt].next=head[x];
    head[x]=cnt++;
}
int n,m;
void dfs(int s1,int s2,int b1,int b2,int step)
{
    if(step==m)
    {
        if(!b1&&!b2)
        {
            add(s1,s2);
        }
        return ;
    }
    dfs(s1|(b1<<step),s2|((1-b2)<<step),0,0,step+1);
    if(!b1 && !b2)
    {
        dfs(s1|(1<<step),s2,0,0,step+1);
        dfs(s1|(1<<step),s2,1,0,step+1);
        dfs(s1|(1<<step),s2,0,1,step+1);
    }
    if(!b1)
    {
        dfs(s1|(1<<step),s2|((1-b2)<<step),1,0,step+1);
        dfs(s1|(1<<step),s2|((1-b2)<<step),1,1,step+1);
    }
    if(!b2)
    {
        dfs(s1|(b1<<step),s2,1,1,step+1);
    }    
}
int main()
{ 
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    dfs(0,0,0,0,0);
    f[0][(1<<m)-1]=1;
    for(int i=0;i<n;i++)
    {
        for(int S=0;S<(1<<m);S++)
        {
            if(f[i][S])
            {
                for(int k=head[S];k!=-1;k=e[k].next)
                {
                    f[i+1][e[k].to]+=f[i][S];
                }
            }
        } 
    }
    printf("%lld
",f[n][(1<<m)-1]);
    return 0;
}
View Code
 
原文地址:https://www.cnblogs.com/Winniechen/p/7337304.html