链接:poj2411
题解
- dp[i][j]表示前i行都合法放置的情况下第i行方法为j的方案数
- 这里我们规定当前这位如果不放,那么该位为0,
- 当前这位如果右放,对应两位为1
- 如果下放,当前位为0,下一行的对应位为1
- 由于要求完美覆盖,我们可以预处理出所有合法放置及关系,然后一个简单状压dp就解决了(不预处理也能AC)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
using namespace std;
const int N=15;
const int M=1<<11;
int n,m,path[M*M+7][2],cnt;
ll dp[N][M];
inline void get(int a,int pre,int now){
if(a>m)return ;
if(a==m){
path[++cnt][0]=pre;
path[cnt][1]=now;
}
get(a+1,pre<<1|1,now<<1); //不放
get(a+1,pre<<1,now<<1|1); //上方
get(a+2,pre<<2|3,now<<2|3); //右放
}
int main(){
while(~scanf("%d%d",&n,&m)&&(n||m)){
cnt=0;
get(0,0,0);
memset(dp,0,sizeof dp);
dp[0][(1<<m)-1]=1;
rep(i,1,n)rep(j,1,cnt)dp[i][path[j][1]]+=dp[i-1][path[j][0]];
printf("%lld\n",dp[n][(1<<m)-1]);
}
return 0;
}