LightOJ 1270 Tiles (II)

题目:http://lightoj.com/login_main.php?url=volume_showproblem.php?problem=1270

题意:给你一个n*m的棋盘 让你用6种砖块填满它,问一共有多少种(砖块不能旋转或翻转)

 

写的时候要注意很多细节,不然很容易写错

因为这里的轮廓线要m+1的长度,所以去下一层的时候必须变换一下状态

将最高位放到最低位,其他都向前移一位

之后就是麻烦的分类讨论,具体看代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
typedef unsigned long long ll;
char a[105][105];
int now=0,pre=1;
ll dp[2][1<<12];
int main()
{
    int T;
    scanf("%d",&T);
    for(int ca=1;ca<=T;ca++)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        if (n>=m)
        {
            for(int i=0;i<n;i++)
                scanf("%s",a[i]);
        }
        else
        {
            swap(n,m);
            for(int j=0;j<m;j++)
                for(int i=n-1;i>=0;i--)
                    scanf(" %c",&a[i][j]);
        }
        int tot=1<<(m+1);
        memset(dp[now],0,sizeof(dp[now]));
        dp[now][tot-1]=1;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                swap(now,pre);
                memset(dp[now],0,sizeof(dp[now]));
                for(int st=0;st<tot;st++)
                    if (dp[pre][st])
                {
                    if (a[i][j]=='.')
                    {
                        if (st&1<<j && !(st&1<<(j+1)))//1
                            dp[now][st|1<<(j+1)]+=dp[pre][st];
                        if (j && j<m-1&& st&1<<j && !(st&1<<(j-1)))//2
                            dp[now][st|1<<(j-1)]+=dp[pre][st];
                        if (j && j==m-1 && st&1<<(j+1) && st&1<<j && !(st&1<<(j-1)))//2
                            dp[now][st|1<<(j-1)]+=dp[pre][st];
                        if (j && j<m-1 && !(st&1<<(j-1)) && !(st&1<<j))//3
                            dp[now][st|1<<(j-1)|1<<j]+=dp[pre][st];
                        if (j && j==m-1 && !(st&1<<(j-1)) && !(st&1<<j) && st&1<<(j+1))//3
                            dp[now][st|1<<(j-1)|1<<j]+=dp[pre][st];
                        if (j<m-1 && st&1<<j && !(st&1<<(j+1)) && !(st&1<<(j+2)))//4
                            dp[now][st|1<<(j+1)|1<<(j+2)]+=dp[pre][st];
                        if (j && st&1<<j && !(st&1<<(j-1)) && !(st&1<<(j+1)))//5
                            dp[now][st|1<<(j-1)|1<<(j+1)]+=dp[pre][st];
                        if (j && !(st&1<<j) && !(st&1<<(j+1)))//6
                            dp[now][st|1<<j|1<<(j+1)]+=dp[pre][st];
                        if (j==m-1)//不放
                        {
                            if (st&1<<j&&st&1<<(j+1))
                                dp[now][st&~(1<<j)]+=dp[pre][st];
                        }
                        else//不放
                        {
                            if (st&1<<j)
                                dp[now][st&~(1<<j)]+=dp[pre][st];
                        }
                    }
                    else//不能放
                    {
                        if (j==m-1)
                        {
                            if (st&1<<j&&st&1<<(j+1))
                                dp[now][st]+=dp[pre][st];
                        }
                        else
                        {
                            if (st&1<<j)
                            dp[now][st]+=dp[pre][st];
                        }
                    }
                }
            }
            swap(now,pre);
            memset(dp[now],0,sizeof(dp[now]));
            for(int st=0;st<tot;st++)
                if (dp[pre][st])
                    dp[now][(st<<1|st>>m)%tot]=dp[pre][st];
        }
        printf("Case %d: %llu\n",ca,dp[now][tot-1]);
    }
    return 0;
}

  

  

posted @ 2017-09-06 14:08  BK_201  阅读(155)  评论(0编辑  收藏  举报