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

来源:互联网 发布:日本历史地震数据统计 编辑:程序博客网 时间:2024/06/10 04:09

炮兵阵地
Time Limit: 2000MS Memory Limit: 65536KTotal Submissions: 19226 Accepted: 7424

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

一道简单的状态压缩DP题,对于这种题,一般是先预处理出可行的状态,用二进制压缩状态,再对每一行的状态进行枚举。

这道题由于每个炮兵可以攻击两行,所以要多枚举一行。可以通过预处理的方式来处理上下两行状态的关系。

状态转移方程: dp[i][j][k],i代表层数,j代表当前行的状态id,k代表上一行的状态id

那么 dp[i][j][k]  = max(dp[i][j][k],dp[i][k][l]+num[j]) ,l是上上层的状态,枚举j,k,l即可

AC代码如下:

#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn = (1<<10)+10;int n,m;char ma[105][15];int state[100];int num[100];int dp[105][100][100];int flag[100][100];int che[105][maxn];int check(int x,int p){    if(che[x][p]!=-1)return che[x][p];    for(int i=0;i<m;i++)        if((p & (1<<i)) && ma[x-1][i] == 'H')return che[x][p] = 0;    return che[x][p] = 1;}int main(){    int sz = 0;    for(int i=0;i<maxn;i++)        if((i&(i<<1))==0&&(i&(i<<2))==0)state[sz++] = i;    for(int j=0;j<sz;j++)        for(int i=0;i<11;i++)            if((state[j] & (1<<i)))num[j]++;    for(int i=0;i<sz;i++)        for(int j=0;j<sz;j++)            if((state[j]&state[i])==0)flag[i][j] = 1;    //cout<<sz<<endl;    while(scanf("%d%d",&n,&m)==2){        memset(che,-1,sizeof(che));        for(int i=0;i<n;i++)            scanf("%s",ma[i]);        memset(dp,0,sizeof(dp));        for(int i=1;i<=n;i++)        {            for(int j=0;state[j]<(1<<m);j++){                if(!check(i,state[j]))continue;                if(i == 1){dp[i][j][0] = num[j];continue;}                if(i == 2){                    for(int k=0;state[k]<(1<<m);k++)                        if(flag[j][k]&&check(i-1,state[k]))dp[i][j][k] = dp[i-1][k][0]+num[j];                    continue;                }                for(int k=0;state[k]<(1<<m);k++){                    if(!check(i-1,state[k])||!flag[j][k])continue;                    for(int l=0;state[l]<(1<<m);l++)                        if(check(i-2,state[l])&&flag[j][l]&&flag[k][l])                            dp[i][j][k] = max(dp[i][j][k],num[j]+dp[i-1][k][l]);                }            }        }        int ans = 0;        for(int j=0;state[j]<(1<<m);j++)            for(int k=0;state[k]<(1<<m);k++)                ans = max(ans,dp[n][j][k]);        cout<<ans<<endl;    }    return 0;}/*5 4PHPPPPHHPPPPPHPPPHHP10 10PPPPPPPPPPHHPPPPPPHHPPPPPPPPPPHHPPPPPPHHPPPPPPPPPPHHPPPPPPHHPPPPPPPPPPHHPPPPPPHHPPPPPPPPPPHHPPPPPPHH*/

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 龙妈和雪诺怎么办 车本扣6分怎么办 超速50扣了12分怎么办 开车超速扣12分怎么办 超速一次记12分怎么办? 驾照超速扣12分怎么办 c牌一次扣12分怎么办 超速罚500扣12分怎么办 高速超速记3分怎么办 高速超速记12分怎么办 过江隧道关闭了怎么办 高速限速60超了怎么办 超速扣了12分怎么办 上海 12分扣完了怎么办 狗抓伤只淌白沫怎么办 刑事案件法院迟迟不判决怎么办 法院判决书下来了没钱赔偿怎么办 被起诉开庭不去怎么办 地道塌陷造成房屋倒塌怎么办 海外看不了b站怎么办 最近脸胖了好多怎么办 最近胖了好多怎么办啊? 很瘦的人手胖怎么办 长得丑不敢相亲怎么办 abs抱死发不动了怎么办 qq飞车手游车到期了改装怎么办 育碧下载游戏慢怎么办 豹纹守宫鼻子还有个残皮怎么办 睫角守宫断尾怎么办 定金发票弄丢了怎么办 xp电脑显示输入不支持怎么办 月子见风怎么办暴雪将 老氏电视机出现雪花点怎么办 飞利浦电视显示雪花片怎么办 电视无信号出雪花怎么办 电视打开都是雪花没有电视台怎么办 电视视频1无信号怎么办 新买的电视无信号怎么办 卫星有信号没有视频怎么办 户户通没有信号怎么办视频 雪花泥粘衣服上怎么办