给出N*M的地图,有很多空地P跟山地H,炮台可以攻击周边:
求最多能放多少个炮台并且他们互不攻击。
N≤100;M≤10
这题是状压dp的一道经典题目,
对于每行10个东东可以放就是2^10种可能,这样转移就会TLE
所以我们发现因为任意2个炮之间距离至少为2,所以我们每行存在的可行状态至多不超过2^5
因此我们暴力处理出每行的这些状态以及
每个状态存在多少个炮台即可。
然后去dp即可
设f[i,k,j]表示选到了第i行,第i行状态为s[k],第i-1行状态为s[j]时的最大能放数量。
推得转移方程:
f[i,k,j]=max{f[i,k,j],f[i-1,j,l]+num[s[i]]}
l为i-2行的状态
注意判断第i,i-1,i-2行的状态是否冲突
var
f:array [-5..101,0..61,0..61] of longint;
s:array [-5..101,0..61] of longint;
a:array [0..101,0..11] of char;
num,c:array [0..1025] of longint;
b:array [0..11] of longint;
ans,ans1,i,j,k,l,p,n,m:longint;
check:boolean;
function max(aa,bb:longint):longint;
begin
if aa>bb then exit(aa);
exit(bb);
end;
procedure dfs(dep,now,cp:longint);
var
j:longint;
begin
if c[now]<>i then
begin
c[now]:=i;
if num[now]=0 then num[now]:=cp;
inc(s[i,0]);
s[i,s[i,0]]:=now;
end;
if dep=m then exit;
for j:=dep+1 to m do
if (a[i,j]='P') and (b[j]<>i) then
begin
b[j+1]:=i;
b[j+2]:=i;
dfs(j,now+1 shl (j-1),cp+1);
b[j+1]:=0;
b[j+2]:=0;
end;
dfs(dep+1,now,cp);
end;
begin
readln(n,m);
for i:=1 to n do
begin
for j:=1 to m do read(a[i,j]);
dfs(0,0,0);
readln;
end;
ans:=0;
for i:=1 to s[1,0] do
f[1,i,1]:=num[s[1,i]];
s[0,0]:=1; s[0,1]:=0;
for i:=2 to n do
for j:=1 to s[i,0] do
for k:=1 to s[i-1,0] do
if s[i,j] and s[i-1,k]=0 then
for l:=1 to s[i-2,0] do
if s[i-2,l] and s[i,j]=0 then
if s[i-2,l] and s[i-1,k]=0 then
begin
f[i,j,k]:=max(f[i,j,k],f[i-1,k,l]+num[s[i,j]]);
ans:=max(ans,f[i,j,k]);
end;
writeln(ans);
end.