[BZOJ1725] [Usaco2006 Nov]Corn Fields牧场的安排

传送门

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.

你可能感兴趣的:([BZOJ1725] [Usaco2006 Nov]Corn Fields牧场的安排)