1. 程式人生 > >[NOI2001]炮兵陣地

[NOI2001]炮兵陣地

題目描述

司令部的將軍們打算在NM的網格地圖上部署他們的炮兵部隊。一個NM的地圖由N行M列組成,地圖的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下圖。在每一格平原地形上最多可以佈置一支炮兵部隊(山地上不能夠部署炮兵部隊);一支炮兵部隊在地圖上的攻擊範圍如圖中黑色區域所示:

如果在地圖中的灰色所標識的平原上部署一支炮兵部隊,則圖中的黑色的網格表示它能夠攻擊到的區域:沿橫向左右各兩格,沿縱向上下各兩格。圖上其它白色網格均攻擊不到。從圖上可見炮兵的攻擊範圍不受地形的影響。 現在,將軍們規劃如何部署炮兵部隊,在防止誤傷的前提下(保證任何兩支炮兵部隊之間不能互相攻擊,即任何一支炮兵部隊都不在其他支炮兵部隊的攻擊範圍內),在整個地圖區域內最多能夠擺放多少我軍的炮兵部隊。

輸入輸出格式

輸入格式:

第一行包含兩個由空格分割開的正整數,分別表示N和M;

接下來的N行,每一行含有連續的M個字元(‘P’或者‘H’),中間沒有空格。按順序表示地圖中每一行的資料。N≤100;M≤10。

輸出格式:

僅一行,包含一個整數K,表示最多能擺放的炮兵部隊的數量。

輸入輸出樣例

輸入樣例#1:

5 4
PHPP
PPHH
PPPP
PHPP
PHHP

輸出樣例#1:
6


狀壓dp

由於\(M\leq 10\)而且相鄰3個位置內不能放兩個以上炮兵,所以其實真正每行能放的狀態是很少的。
其實每一次對新的一行轉移時對他有影響的只有向上兩行,加到狀態裡就行了。
那麼先找出每一種可行的狀態,兩兩看是否匹配。
暴力轉移即可


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
#define max(a,b) ((a)>(b)? (a):(b))
#define min(a,b) ((a)<(b)? (a):(b))

using namespace std;

int b[101],i,m,n,j,k,a[101][101][101],d[100],v[100],bl[101][101],l,ans,bb[101][101][101];
char c;
int main()
{
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++) 
        {
            b[i]<<=1;
            scanf("%c",&c);
            while(c!='P' && c!='H') scanf("%c",&c);
            if(c=='H') b[i]+=1;
        }
        
    for(i=0;i<=(1<<m)-1;i++)
    {
        if((i&(i<<1))||(i&(i<<2))) continue;
        int t=i; k=0;
        while(t) t-=t & -t, k+=1;
        v[++v[0]]=k;
        d[++d[0]]=i;
    }
    
    for(i=1;i<=d[0];i++) 
        if(!(b[1]&d[i]))  
        {
            bb[1][1][i]=1;
            a[1][1][i]=v[i];
        }
    for(i=1;i<=d[0];i++)
        for(j=1;j<=d[0];j++) 
            if(!(d[i]&d[j])) bl[i][j]=1;
            
    for(i=2;i<=n;i++)
        for(j=1;j<=d[0];j++)
            for(l=1;l<=d[0];l++)
                if(bb[i-1][j][l])
                for(k=1;k<=d[0];k++)
                if(bl[k][l] && bl[k][j] &&(!(d[k]&b[i])))
                {
                    bb[i][l][k]=1;
                    a[i][l][k]=max(a[i][l][k],a[i-1][j][l]+v[k]);
                    if(i==n) ans=max(ans,a[i][l][k]);
                }
                
    printf("%d",ans);
}