炮兵阵地
Time Limit:1000MS Memory Limit:65536K
Total Submit:30 Accepted:14
Description
司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队。一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:
如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。
现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。
Input
第一行包含两个由空格分割开的正整数,分别表示N和M;
接下来的N行,每一行含有连续的M个字符(‘P’或者‘H’),中间没有空格。按顺序表示地图中每一行的数据。N≤100;M≤10。
Output
仅在第一行包含一个整数K,表示最多能摆放的炮兵部队的数量。
Sample Input
5 4
PHPP
PPHH
PPPP
PHPP
PHHP
Sample Output
6
题目大意:
给出一个N*M的图,图上有一些点可以放棋子,有一些不能。每个棋子的上下左右相邻2个格子内不能放置其他棋子,问最多能放几个棋子。
题解:
状态压缩DP
每一行棋子放置的状态我们可以用一个二进制数表示,那么每一行能放置的所有状态可以预处理得出的。设S[i]为一行中可放置的第i种状态(用DFS求出)
设F[i,j,k]为第i行的状态为第j个状态,i-1行为第k个状态时能放置的最大数量,易得出F[i,j,k]=max(f[i-1,k,l])+c[j] |s[j] s[k] s[l] 不冲突|
C[i]表示第i种状态中1的个数(即放置炮兵的个数)
在DP过程中要判断两个状态不冲突,实际上就是s[i] and s[j]=0,要注意的是图中有一些点不能放炮兵,在读入时要处理出每一行不能放的状态,在判断时使其不与当前行状态冲突。
const
maxn=100;
maxm=100;
var
f:array[0..maxn,0..maxm,0..maxm]of longint;
a:array[-2..maxn]of longint;
s,c:array[0..maxm]of longint;
b:array[0..10]of longint;
n,m,sum,ans,p:longint;
i,j,k,l:longint;
procedure init;
var
i,j:longint;
ch:char;
begin
readln(n,m);
for i:=1 to n do
begin
for j:=1 to m do
begin
read(ch);
if ch='P' then a[i]:=a[i]*2 else if ch='H' then a[i]:=a[i]*2+1;
end;
readln;
end;
sum:=0;
end;
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;
procedure dfs(dep:longint);
var
i:longint;
begin
if dep>m then
begin
inc(sum);s[sum]:=0;
for i:=1 to m do
begin
s[sum]:=s[sum]*2+b[i];
inc(c[sum],b[i]);
end;
exit;
end;
dfs(dep+1);
b[dep]:=1;
dfs(dep+3);
b[dep]:=0;
end;
begin
init;
dfs(1);
for i:=1 to n do
for j:=1 to sum do
for k:=1 to sum do
begin
for l:=1 to sum do
if (s[j] and s[k])+(s[j] and s[l])+(s[k] and s[l])+(s[j] and a[i])+(s[k] and a[i-1])+(s[l] and a[i-2])=0 then
f[i,j,k]:=max(f[i,j,k],f[i-1,k,l]);
f[i,j,k]:=f[i,j,k]+c[j];
end;
for i:=1 to sum do
for j:=1 to sum do
if f[n,i,j]>ans then ans:=f[n,i,j];
writeln(ans);
end.