P5074

Eat the Trees

并不是真的插头 DP(没有要求形成一个闭合回路)。

所以写起来会简单一些。

之前的轮廓线优化都是只用几个格子就能表达状态的信息,而这个插头式的状态我们要存储的就是轮廓“线”上的信息。

我们用 $s$ 表示轮廓线横向的格线是否有插头,并单独再搞出一维看是否有侧向轮廓线上的插头。

定义 $f(i,j,s,k)$ 表示这玩意。。。

剩下就是根据头上和左边是否有插头来搞了。

多测记得清空。

时间复杂度 $O(nm2^m)$。

代码:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include<iostream>
#include<cstdio>
#define ll long long
using namespace std;
namespace Ehnaev{
inline ll read() {
ll ret=0,f=1;char ch=getchar();
while(ch<48||ch>57) {if(ch==45) f=-f;ch=getchar();}
while(ch>=48&&ch<=57) {ret=(ret<<3)+(ret<<1)+ch-48;ch=getchar();}
return ret*f;
}
inline void write(ll x) {
static char buf[22];static ll len=-1;
if(x>=0) {do{buf[++len]=x%10+48;x/=10;}while(x);}
else {putchar(45);do{buf[++len]=-(x%10)+48;x/=10;}while(x);}
while(len>=0) putchar(buf[len--]);
}
}using Ehnaev::read;using Ehnaev::write;
inline void writeln(ll x) {write(x);putchar(10);}

const ll N=12,M=5e3;

ll T,n,m;
ll f[2][N+5][M+5][2],a[N+5][N+5];

int main() {

T=read();

while(T--) {
n=read();m=read();
for(ll i=1;i<=n;i++) {
for(ll j=1;j<=m;j++) {
a[i][j]=read();
}
}
ll tmp=(1ll<<m);
f[0][m][0][0]=1;
for(ll i=1;i<=n;i++) {
for(ll p=0;p<tmp;p++) {
if(p&1) {
if(a[i][1]) {
f[i&1][1][p][0]=f[i&1][1][p][0]+f[(i-1)&1][m][p][0];
f[i&1][1][p^1][1]=f[i&1][1][p^1][1]+f[(i-1)&1][m][p][0];
}
}
else {
if(a[i][1]) {
f[i&1][1][p|1][1]=f[i&1][1][p|1][1]+f[(i-1)&1][m][p][0];
}
else {
f[i&1][1][p][0]=f[(i-1)&1][m][p][0];
}
}
}
for(ll j=2;j<=m;j++) {
for(ll p=0;p<tmp;p++) {
if((p>>(j-1))&1) {
if(a[i][j]) {
f[i&1][j][p][0]=f[i&1][j][p][0]+f[i&1][j-1][p][0];
ll tmpp=(p^(1<<(j-1)));
f[i&1][j][tmpp][1]=f[i&1][j][tmpp][1]+f[i&1][j-1][p][0];
f[i&1][j][tmpp][0]=f[i&1][j][tmpp][0]+f[i&1][j-1][p][1];
}
}
else {
if(a[i][j]) {
f[i&1][j][p][1]=f[i&1][j][p][1]+f[i&1][j-1][p][1];
ll tmpp=(p^(1<<(j-1)));
f[i&1][j][tmpp][0]=f[i&1][j][tmpp][0]+f[i&1][j-1][p][1];
f[i&1][j][tmpp][1]=f[i&1][j][tmpp][1]+f[i&1][j-1][p][0];
}
else {
f[i&1][j][p][0]=f[i&1][j-1][p][0];
}
}
}
}
for(ll j=1;j<=m;j++) {
for(ll p=0;p<tmp;p++) {
f[(i-1)&1][j][p][0]=f[(i-1)&1][j][p][1]=0;
}
}
}
writeln(f[n&1][m][0][0]);
for(ll i=1;i<=m;i++) {
for(ll p=0;p<tmp;p++) {
f[n&1][i][p][0]=f[n&1][i][p][1]=0;
}
}
}

return 0;
}