SGU131 - Hardwood floor(状态压缩DP)

题目大意

给定一个N*M大小的矩形,要求你用1*2和2*2(缺个角)的砖块把矩形铺满(不能重叠),问总共有多少种铺法?

题解

受POJ2411的影响,怎么都没想到3,4,5,6这几种情况该怎么放置,看了网上大牛的解题报告和代码(真是不好的习惯,可是太弱了就是想不出咋办%>_<%)之后豁然开朗~~~~

规模比较小,所以用状态压缩DP来搞,是POJ2411加强版。有以下几种铺法:

##     #.     ##    ##     #.   .#

..     #.     #.    .#     ##   ##

1      2      3      4      5    6
还有一种情况就是不放~~~
我们依然是枚举出合法的当前行以及上一行,不过这里要比POJ2411稍微麻烦点,因为1,3,4,5,6这五种情况当前列的放置会影响后面一列的放置,
所以我们还需要用两个变量来记录是否对下一行有影响,然后就是根据这两个变量的情况进行相应的砖块放置。

代码:

纯模仿。。。

#include<cstdio>

#include<cstring>

#include<iostream>

#include<algorithm>

using namespace std;

#define MAXN 10

typedef long long LL;

LL dp[MAXN][1<<MAXN];

int n,m;

void dfs(int step,int s1,int s2,int u1,int u2,int line)

{

    if(step==m)

    {

        if(!u1&&!u2) dp[line][s2]+=dp[line-1][s1];

        return;

    }

    if(!u2)

    {

        if(!u1)

        {

            dfs(step+1,s1<<1,s2<<1|1,0,0,line);

            dfs(step+1,s1<<1,s2<<1|1,1,0,line);

            dfs(step+1,s1<<1,s2<<1|1,0,1,line);

        }

        dfs(step+1,(s1<<1|1)-u1,s2<<1|1,0,1,line);

        dfs(step+1,(s1<<1|1)-u1,s2<<1|1,1,1,line);

    }

    if(!u1)dfs(step+1,s1<<1,s2<<1|u2,1,1,line);

    dfs(step+1,(s1<<1|1)-u1,s2<<1|u2,0,0,line);

}

int main ()

{

    while(scanf("%d%d",&n,&m)!=EOF)

    {



        memset(dp,0,sizeof(dp));

        dp[0][(1<<m)-1]=1;

        for(int i=1; i<=n; i++)

            dfs(0,0,0,0,0,i);

        printf("%I64d\n",dp[n][(1<<m)-1]);

    }

    return 0;

}

你可能感兴趣的:(OO)