poj 1185 炮兵阵地 状压dp

先dfs把所有可行的状态都找出来。用f[i,j,k]表示第i行状态为j,i-1行状态为k能放置的最多炮兵。r[i]表示第i行哪些格子不能放。若r[i]第j位为1则表示第i行第j位不能放,反之能放。然后dp到第i行的时候判断某种状态是否符合就可以用r[i] and a[j](表示状态)是否为0,为0则符合。f[i,j,k]=max(f[i-1,k,l]+b[j])且满足j、k、l三种状态不冲突  b[j]为第j种状态下的士兵数量。

代码:

var
  n,m,i,j,k,l,ans,a1:longint;
  c:char;
  r,d:array[1..100] of longint;
  a,b:array[1..100] of longint;
  f:array[1..100,0..100,0..100] of longint;

procedure dfs(x:longint);
var
  i:longint;
begin
  if x>m then
  begin
    inc(a1);
    for i:=1 to m do
    begin
      a[a1]:=a[a1]+(1 shl (i-1))*d[i];
      b[a1]:=b[a1]+d[i];
    end;
    exit;
  end;
  dfs(x+1);
  d[x]:=1;
  dfs(x+3);
  d[x]:=0;
end;

begin
  readln(n,m);
  for i:=1 to n do
    for j:=1 to m do
    begin
      if j<m
        then read(c)
        else readln(c);
      if c='H' then r[i]:=r[i]+1 shl (j-1);
    end;
  dfs(1);
  if n=1 then
  begin
    for i:=1 to a1 do
      if (a[i] and r[1]=0)and(b[i]>ans) then ans:=b[i];
    writeln(ans);
    exit;
  end;
  for i:=1 to a1 do
    for j:=1 to a1 do
      if (a[i] and r[1]=0)and(a[j] and r[2]=0)and(a[i] and a[j]=0) then
        f[2,j,i]:=b[j]+b[i];
  for i:=3 to n do
    for j:=1 to a1 do
      if a[j] and r[i]=0 then
        for k:=1 to a1 do
          if (a[k] and r[i-1]=0)and(a[k] and a[j]=0) then
            for l:=1 to a1 do
              if (a[l] and r[i-2]=0)and(a[l] and a[k]=0)and(a[l] and a[j]=0) then
                if f[i-1,k,l]+b[j]>f[i,j,k] then
                  f[i,j,k]:=f[i-1,k,l]+b[j];
  for i:=1 to a1 do
    for j:=1 to a1 do
      if f[n,i,j]>ans then ans:=f[n,i,j];
  writeln(ans);
end.


你可能感兴趣的:(poj 1185 炮兵阵地 状压dp)