题意:给出一个n行m列的草地,1表示肥沃,0表示贫瘠,现在要把一些牛放在肥沃的草地上,但是要求所有牛不能相邻,问你有多少种放法。
分析:假如我们知道第 i-1 行的所有的可以放的情况,那么对于第 i 行的可以放的一种情况,我们只要判断它和 i - 1 行的所有情况的能不能满足题目的所有牛不相邻,如果有种中满足,那么对于 i 行的这一中情况有 x 中放法。
知道这点后就可以用状态压缩DP来搞定。
先把每一行符合的状态枚举出来,然后再DP就好了。
代码:
const p=100000000; var n,m,i,j,k,ans,x,y:longint; a:array[1..12,1..12] of longint; s:array[0..12] of longint; w,f:array[0..12,0..4096] of longint; flag:boolean; begin readln(n,m); for i:=1 to n do for j:=1 to m do read(a[i,j]); s[0]:=1; for i:=1 to m do s[i]:=s[i-1]*2; for i:=1 to n do for j:=0 to s[m]-1 do begin flag:=true; x:=j; k:=0; y:=0; while x>0 do begin inc(k); if (x mod 2<>a[i,k])and(x mod 2=1)or(x mod 2=y)and(y=1) then begin flag:=false; break; end; y:=x mod 2; x:=x div 2; end; if flag then begin inc(w[i,0]); w[i,w[i,0]]:=j; end; end; w[0,0]:=1; w[0,1]:=0; f[0,1]:=1; for i:=1 to n do for j:=1 to w[i,0] do for k:=1 to w[i-1,0] do if w[i-1,k] or w[i,j]=w[i-1,k]+w[i,j] then f[i,j]:=(f[i,j]+f[i-1,k]) mod p; for i:=1 to w[n,0] do ans:=(ans+f[n,i]) mod p; writeln(ans); end.