题意:在n*4的矩阵里,填满1*2的骨牌,有多少种可能性,我想的方向是4列n行
思路:分为三种情况。1.当前列上一行把这一行给占有了,当前行不能再放。
2.当前列上一行没有把这一行给占用,肯定可以竖这放。此时需要占有下一行。
3.当前列和下一列上一行都没把这一行给占用。可以横着放。此时不需要占有。
暴力枚举上一行对这行状态影响,然后dfs枚举出这一行对下一行的状态
dp[i][j]表示第i行对下一行产生j状态的影响的种数
dfs(s,ss,x,n) s是上一行对当前行的影响,即当前行那些被占有了,ss是自己dfs构造这行对下一行的影响,
x是dfs处理到第几列0-3,n是在处理第几行。
最后把dp[n][0]输出就好即不对下一行产生影响
#include<bits/stdc++.h>
using namespace std;
long long dp[30][16];
void dfs(int s,int ss,int x,int n) {
///s上一行对这一行的影响,(即当前行的状态),ss当前行构造的对下一行的影响
///x正在处理第几列,n正在处理第几行 该矩阵是4列n行的
if(x>3) { ///全部处理完了
dp[n+1][ss]+=dp[n][s];
return;
}
if(s&(1<<x)) { ///如果上一行已经占有这一行的这一格了直接跳过
dfs(s,ss,x+1,n);
return;
}
dfs(s,ss|(1<<x),x+1,n); ///竖着放已经确定该行没被占用。
if(x<=2&&!(s&(1<<(x+1)))) { ///横着放,先确认下一行有没有被占用
dfs(s,ss,x+2,n);///横着放并不会影响下一行。
}
return;
}
int main()
{
memset(dp,0,sizeof dp);
dp[0][0]=1;
for(int i=0;i<25;i++)
for(int j=0;j<16;j++) {
if(dp[i][j]) {
dfs(j,0,0,i);
}
}
int t,n;
int kase=0;
scanf("%d",&t);
while(t--) {
scanf("%d",&n);
printf("%d %lld\n",++kase,dp[n][0]);
}
return 0;
}