[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);
}

猜你喜欢

转载自www.cnblogs.com/ZUTTER/p/9805601.html