http://cojs.tk/cogs/problem/problem.php?pid=301
给定01棋盘,1可以放炮兵,每个炮兵间x和y轴距离大于等于2,询问最多放几个
状压DP
根据[BZOJ1725] [Usaco2006 Nov]Corn Fields牧场的安排就可以设计出相似的状态(那道题是相隔1位,这个是相隔2位)
dp[i,j,k]:表示第i行状态为j,第i−1行状态为k
dp[i,j,k]=max(dp[i−1,k,l]+sum[j],dp[i,j,k])
我们要预处理出所有状态,我们会发现,状态最多有60种…
O(n603)
var
x:array[0..200,0..20]of longint;
sum,y:array[0..200]of longint;
z:array[0..200,0..100]of longint;
dp:array[0..200,0..200,0..200]of longint;
i,j,k,l:longint;
n,m,t,ans:longint;
cha:char;
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;
procedure prepare;
var a,b,c,d,summ:longint;
begin
t:=1;
for i:=0 to (1<1 do
begin
l:=1; summ:=0;
for j:=1 to m do
begin
a:=0; b:=0; c:=0; d:=0;
if i and(1<<(j-1))=0 then continue else inc(summ);
if j-1>0 then a:=i and(1<<(j-2));
if j-2>0 then b:=i and(1<<(j-3));
if j+1<=m then c:=i and(1<<(j));
if j+2<=m then d:=i and(1<<(j+1));
if (a<>0)or(b<>0)or(c<>0)or(d<>0) then begin l:=0; break; end;
end;
if l=1 then begin y[t]:=i; sum[t]:=summ; inc(t); end;
end;
dec(t);
for i:=1 to n do
for j:=1 to t do
begin
z[i,j]:=1;
for k:=1 to m do
if (y[j] and(1<<(k-1))<>0)and(x[i,k]=0)
then begin z[i,j]:=0; break; end;
end;
for j:=1 to t do
for k:=1 to t do
if (z[2,j]=1)and(z[1,k]=1)and(y[j]and y[k]=0)
then dp[2,j,k]:=sum[j]+sum[k];
end;
begin
readln(n,m);
for i:=1 to n do
begin
for j:=1 to m do
begin read(cha); if cha='P' then x[i,j]:=1 else x[i,j]:=0; end;
readln;
end;
prepare;
for i:=3 to n do
for j:=1 to t do
if z[i,j]=1 then
for k:=1 to t do
if z[i-1,k]=1 then
for l:=1 to t do
if (z[i-2,l]=1)and(y[l] and y[k]=0)and((y[l] or y[k])and y[j]=0)
then dp[i,j,k]:=max(dp[i,j,k],dp[i-1,k,l]+sum[j]);
ans:=0;
for i:=1 to t do
for j:=1 to t do
ans:=max(ans,dp[n,i,j]);
writeln(ans);
end.