POJ 1185 炮兵阵地(状态压缩DP)

来源:互联网 发布:java生成dump文件命令 编辑:程序博客网 时间:2024/06/05 00:11

B - 炮兵阵地
Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u
Submit Status

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 4PHPPPPHHPPPPPHPPPHHP

Sample Output

6


题解:nState为状态数,state数组为可能的状态

代码:

#include <map>#include <set>#include <list>#include <cmath>#include <queue>#include <stack>#include <vector>#include <cstdio>#include <string>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int INF=0x3f3f3f3f;typedef long long ll;typedef unsigned long long ull;#define fi first#define se second#define prN printf("\n")#define SI(N) scanf("%d",&(N))#define SII(N,M) scanf("%d%d",&(N),&(M))#define SIII(N,M,K) scanf("%d%d%d",&(N),&(M),&(K))#define cle(a,val) memset(a,(val),sizeof(a))#define rep(i,b) for(int i=0;i<(b);i++)#define Rep(i,a,b) for(int i=(a);i<=(b);i++)int n,m,dp[105][80][80];int row[105];int nState,state[80],num[80];void init(){    int k=1<<m;    nState=0;    rep(i,k)    {        if ((i&(i<<1))==0&&(i&(i<<2))==0)        {            state[nState]=i;            num[nState]=0;            int j=i;            while(j)            {                num[nState]+=j%2;                j/=2;            }            nState++;        }    }}int main(){#ifndef ONLINE_JUDGE    freopen("C:\\Users\\Zmy\\Desktop\\in.txt","r",stdin);//    freopen("C:\\Users\\Zmy\\Desktop\\out.txt","w",stdout);#endif // ONLINE_JUDGE    char str[20]= {0};    while(cin>>n>>m)    {        init();        rep(i,n)        {            row[i]=0;            scanf("%s",str);            rep(j,m)            {                if (str[j]=='P')                {                    row[i]+=1<<j;                }            }        }        cle(dp,0);        rep(j,nState)        {            if ((state[j]&row[0])!=state[j])            {                continue;            }            rep(k,nState)            {                dp[0][j][k]=num[j];            }        }        if (n>1)            rep(j,nState)        {            if ((state[j]&row[1])!=state[j])            {                continue;            }            rep(k,nState)//这的k代表的是上上个            {                if ((state[j]&state[k])==0)                {                    dp[1][j][k]=dp[0][k][0] + num[j];/**< 这是啥意思?? */                }            }        }        Rep(i,2,n-1)        {            rep(j,nState)            {                if ((state[j]&row[i])!=state[j])                {                    continue;                }                rep(k,nState)//这的k代表的是上上个                {                    if ( state[j] & state[k] )                        continue;                    for (int h = 0; h < nState; h++)/**< i是这个,j是上1,k是上2,h是上3 */                    {                        if ( state[j] & state[h] )                            continue;                        if ( dp[i-1][k][h] > dp[i][j][k] )                            dp[i][j][k] = dp[i-1][k][h];                    }                    dp[i][j][k] += num[j];                }            }        }        int maxa = 0;        for (int j = 0; j < nState; j++)        {            for (int k = 0; k < nState; k++)                if (maxa < dp[n-1][j][k])                    maxa = dp[n-1][j][k];        }        printf("%d\n", maxa);    }    return 0;}

0 0
原创粉丝点击