题目: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 ",ca,dp[now][tot-1]); } return 0; }