http://www.lydsy.com/JudgeOnline/problem.php?id=1725
给定nxm的01格子,1的格子可以放东西,放了东西后这个格子的四连通就不能放了,询问有多少种放法
n和m很小,状压DP
我们定义dp[i,j]:第i行的状态为j的放法总和
怎么判断呢:枚举第i层的状态和第i-1层的状态,如果合法就转移
怎么合法呢:
1.两行中没有位置相同且都为1的,即(j and k=0)
2.两行的状态j和k都是合法的,即他们放的位置都是1且他们放的位置两边都是0
var
x:array[0..20,0..20]of longint;
y,dp:array[0..20,0..5000]of longint;
i,j,k:longint;
n,m,ans:longint;
begin
readln(n,m);
for i:=1 to n do
for j:=1 to m do
read(x[i,j]);
for i:=1 to n do
for j:=0 to (1<<m)-1 do
begin
y[i,j]:=1;
for k:=1 to m do
begin
if (j and (1<<(k-1))<>0)and(x[i,k]=0)
then begin y[i,j]:=0; break; end;
if (k=1)and(j and (1<<(k-1))<>0)and(j and (1<<k)<>0)
then begin y[i,j]:=0; break; end;
if (k=m)and(j and (1<<(k-1))<>0)and(j and(1<<(k-2))<>0)
then begin y[i,j]:=0; break; end;
if (k<>1)and(k<>m)and(j and (1<<(k-1))<>0)and((j and (1<<k)<>0)or(j and(1<<(k-2))<>0))
then begin y[i,j]:=0; break; end;
end;
end;
for i:=0 to (1<<m)-1 do
dp[1,i]:=y[1,i];
for i:=2 to n do
for j:=0 to (1<<m)-1 do
for k:=0 to (1<<m)-1 do
if (y[i,j]=1)and(y[i-1,k]=1)and(j and k=0)
then dp[i,j]:=(dp[i,j]+dp[i-1,k])mod 100000000;
ans:=0;
for i:=0 to (1<<m)-1 do
ans:=(ans+dp[n,i])mod 100000000;
writeln(ans);
end.