NOI2001《炮兵陣地》 狀壓DP

2021-07-11 05:40:56 字數 2849 閱讀 5589

炮兵陣地

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.

NOI 2001 炮兵陣地

分析 本來想的和周偉nei胖子差不多 但是感覺時間會炸,於是又苟且看了講解 發現胖子果然用會炸的方法 但是畢竟十幾年前的題了 資料略弱 dp i j k 表示前i行中,第i行狀態為j,第i 1行狀態為k時炮兵的最多數量 狀態均為01的二進位制串 方程很好寫 dp i j k max dp i j k...

NOI2001 炮兵陣地

司令部的將軍們打算在n m的網格地圖上部署他們的炮兵部隊。乙個n m的地圖由n行m列組成,地圖的每一格可能是山地 用 h 表示 也可能是平原 用 p 表示 如下圖。在每一格平原地形上最多可以布置一支炮兵部隊 山地上不能夠部署炮兵部隊 一支炮兵部隊在地圖上的攻擊範圍如圖中黑色區域所示 如果在地圖中的括...

NOI2001 炮兵陣地

司令部的將軍們打算在n m的網格地圖上部署他們的炮兵部隊。乙個n m的地圖由n行m列組成,地圖的每一格可能是山地 用 h 表示 也可能是平原 用 p 表示 如下圖。在每一格平原地形上最多可以布置一支炮兵部隊 山地上不能夠部署炮兵部隊 如果在地圖中的括號所標識的平原上部署一支炮兵部隊,則圖中的黑色的網...