状态压缩 dp
f[i][t]
是指前
i−1
行填满,第
i
行状态为
记
full
为将一行填满的状态,可知
t
^
本题比较适合
DFS
逐行
dp
记
row
行状态为
t1,row+1
行状态为
t2
,
s−1
列影响
s
列状态为
下面分7种情况讨论:
(1)当我们不在当前行当前列放
block
时
0 0
0 0
dfs(s+1,t1<<1|p1, t2<<1|p2,0 ,0);
(2)当横着放
block
时,即为:
1 1
0 0
dfs(s+1,t1<<1|1,t2<<1|p2,1,0); | p1 = 0
(3)当竖着放
block
时,即为:
1 0
1 0
dfs(s+1,t1<<1|1,t2<<1|1,0,0); | p1 = 0 & p2 = 0
(4)当
L
形如此放时,即为:
1 0
1 1
dfs(s+1,t1<<1|1,t2<<1|1,0,1); | p1 = 0 & p2 = 0
(5)当
1 1
1 0
dfs(s+1,t1<<1|1,t2<<1|1,1,0); | p1 = 0 & p2 = 0
(6)当
L
形如此放时,即为:
0 1
1 1
dfs(s+1,t1<<1|1,t2<<1|p2,1,1); | p2 = 0
(7)当
1 1
0 1
dfs(s+1,t1<<1|1,t2<<1|p2,1,1); | p1 = 0
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
const int MAXN = 11;
int n,m;
long long f[MAXN][1<<MAXN] = {0};
int full , row;
void dfs(int s , int t1 , int t2 , int p1 , int p2)
{
if(s > m)
{
if(!p1 && !p2)f[row+1][t2] += f[row][t1^full];
return ;
}
dfs(s+1,t1<<1|p1, t2<<1|p2,0 ,0);
if(!p1)
{
dfs(s+1,t1<<1|1,t2<<1|p2,1,0);
dfs(s+1,t1<<1|1,t2<<1|p2,1,1);
}
if(!p2)
{
dfs(s+1,t1<<1|p1,t2<<1|1,1,1);
}
if((!p1) && (!p2))
{
dfs(s+1,t1<<1|1,t2<<1|1,0,0);
dfs(s+1,t1<<1|1,t2<<1|1,0,1);
dfs(s+1,t1<<1|1,t2<<1|1,1,0);
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("sgu131.in","r",stdin);
freopen("sgu131.out","w",stdout);
#endif
std::cin >> n >> m;
full = (1<<m) - 1;
f[1][0] = 1;
for(int i = 1 ; i <= n ; i++)
{
row = i;
dfs(1 , 0 , 0 , 0 , 0);
row = 0;
}
std::cout << f[n + 1][0];
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}