题目: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;
}