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

题目链接:http://poj.org/problem?id=1185

题意:

给 N,M(N<=100,M<=10),之后给出一个 N*M 由 "H"、"P" 组成的一个矩阵,H--代表山地,P--代表平原,一架炮的攻击范围如图所示;炮可以攻击 H(山地),但只能架在P(平原),在防止误伤的前提下(即炮不可以架在攻击范围之内,但攻击范围可以重叠),求整个区域最多能摆多少架炮?不是求方案数,不是求方案数,不是求方案数。

思路:

1.仔细分析问题后,发现该问题可以抽象为 0 1 的子问题,即假设 1 为有炮,0 为没有炮,最终答案是一个 N*M 的0 1矩阵中1的个数。

 既然如此,先将N*M的H,P矩阵转换为01矩阵,再将其按行压缩为十进制的一维数组保。代码如下

char c;
for(int i=1;i<=N;++i)
{
    int Sum=0;
    for(int j=M-1;j>=0;--j)
    {
        cin>>c;
        if(c=='P')
            Sum+=(1<

 

2.再进行防止误伤的分析时,将每一个炮分为横向防止误伤,纵向防止误伤两种情况来处理。对横向防误伤可以进行预处理,只将不会进行相互攻击的情况提前找出来(即找出两个1之间有两个即两个以上0的情况), 再看条件M<=10,最多有1024中 0 1的全排列,所以符合的状态最多有60种。代码如下

init(0,0);//main()中的接口
//普通递归函数求符合解,并保存
void init(int i,int flag)
{
    if(i==M)
    {
        sta[sum]=0;//sta[]为保存符合的状态
        sta_n[sum]=0;//sta_n[]为保存符合状态中1的个数
        int n=0;
        for(int i=0;i

3.对于处理纵向防误伤,由状态转移方程处理:dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][p]+sta_n[j]);(就是把第 i 行前两行(因为当且仅当第 i 行的前两行会影响第 i 行)的所有状态枚举出来,求出最值)

dp[i][j][k]:表示第 i 行,第 j 种状态在第 i-1 行是第 k 种状态的情况下最多的炮台数目;第1行和第2行另行处理;最大值不一定是在第 N 行出现(不是求方案数,所以要求全体最值)。代码如下

    int ans=0;
    if(N>=1)
    {
        for(int j=0;j=2)
    {
        for(int j=0;j

AC代码:

#include
#include
#include
using namespace std;
int num[20],sum=0,sta[65],sta_n[65];
int a[110],dp[110][65][65];
int N,M;
void init(int i,int flag)
{
    if(i==M)
    {
        sta[sum]=0;
        sta_n[sum]=0;
        int n=0;
        for(int i=0;i>N>>M;
    init(0,0);
    for(int i=1;i<=N;++i)
    {
        int Sum=0;
        for(int j=M-1;j>=0;--j)
        {
            cin>>c;
            if(c=='P')
                Sum+=(1<=1)
    {
        for(int j=0;j=2)
    {
        for(int j=0;j

  

 

转载于:https://www.cnblogs.com/l1l1/p/8553211.html

你可能感兴趣的:(POJ--1185--炮兵阵地(状态压缩DP))