poj 3254 Corn Fields 状态压缩DP

题意:给出一个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.


你可能感兴趣的:(poj 3254 Corn Fields 状态压缩DP)