zoukankan      html  css  js  c++  java
  • poj1185 炮兵阵地 经典状态压缩dp

    这个题目和上一个种玉米的是一个类型,都是状态dp,用二进制位来表示当前的一个状态值,只不过比上一个稍微复杂了一点,需要用三维的数组来保存当前state。

    题目:在一个N*M的矩阵上布置炮兵部队,只有平原可以布置,然后每个炮兵部队都有一个攻击范围,它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。

    问:如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区

    域内最多能够摆放多少我军的炮兵部队?

    由于是求的最多能放置的炮兵个数,就是求某一个状态下,它对应的炮兵个数最多,所以就想到dp方程肯定是那种dp[i+1]=max{dp[i-1]..}的形式,又考虑到每一行

    的状态只和前两行有关系,所以考虑用dp来做,下面考虑如何用二进制位来表示一个状态及转移方程。

    对于原始的矩阵,我们用1来表示可以放置炮兵,即对应图中的P,这样每一行都有一个可以放置炮兵的状态,存到rstate[N]中,用来check该行的状态是否合法。

    由于当前行和前两行有关系,所以得用3维矩阵来保存一个状态下最多的炮兵个数,用dp[i][curst][prest]表示当前第i行状态对curst,前一行状态为prest的最大炮兵数。

    转移方程为dp[i][curst][prest]=max{dp[i-1][prest][preprest]},这样求到最后一行之后,答案就是最后一行所有状态中最大的那个。程序初始化的时候需要对第一行

    进行预处理,设置dp[0][st][0]=st合法&st中1的个数。这样进行下面的计算的时候,由于0状态肯定是和所有状态兼容的,所以就不会影响计算结果。

    代码如下:

    View Code
    #include <iostream>
    #include <stdio.h>
    using namespace std;
    const int N = 101;
    const int M=11;
    const int MAXS = 61;
    char matrix[N][M];
    int dp[N][MAXS][MAXS];
    int vst[MAXS];
    int num[MAXS];
    int rstate[N];
    int vnum = 0, n = 0, m = 0;
    int getnum(int i)
    {
        int ret = 0;
        while(i)
        {
            i &= i - 1;
            ++ret;
        }
        return ret;
    }
    void initstate()
    {
        vnum = 0;
        for(int i = 0; i < (1<<m); ++i)
        {
            if(!(i&(i<<1)) && !(i&(i<<2)))
            {
                vst[vnum] = i;
                num[vnum++] = getnum(i);
            }
        }
    }
    int main()
    {
        int i = 0, j = 0, k = 0, t = 0;
        while(EOF != scanf("%d%d", &n, &m))
        {
            for(i = 0; i < n; ++i)
            {
                rstate[i] = 0;
                scanf("%s", matrix[i]);
                for(j = 0; j < m; ++j)
                {    
                    if('P' == matrix[i][j])
                    {
                        rstate[i] += (1<<(m-j-1));
                    }
                }
            }
            for(i = 0; i < n; ++i)
                for(j = 0; j < MAXS; ++j)
                    for(k = 0; k < MAXS; ++k)
                        dp[i][j][k] = -1;
            initstate();
            for(i = 0; i < vnum; ++i)
                if(!(vst[i]&(~rstate[0])))
                    dp[0][i][0] = num[i];
           //dp[i][j][k] = max{dp[i][j][k], dp[i-1[k][t]]+num[j]}
           for(i = 1; i < n; ++i)
           {
               for(j = 0; j < vnum; ++j)// state of row i
               {
                   if((~rstate[i])&vst[j])
                       continue;
                   for(k = 0; k < vnum; ++k)//state of row i-1
                   {
                       if((~rstate[i-1])&vst[k])
                           continue;
                       if(vst[j]&vst[k])
                           continue;
                       for(t = 0; t < vnum; ++t)//state of row i-2
                       {
                         if(vst[j]&vst[t])
                             continue;
                         if(-1 == dp[i-1][k][t])
                             continue;
                         dp[i][j][k]=(dp[i][j][k]>=dp[i-1][k][t]+num[j])?dp[i][j][k]:dp[i-1][k][t]+num[j];
                       }
                   }
               }
           }
           int ret = 0;
           for(i = 0; i < vnum; ++i)
           {
               for(j = 0; j < vnum; ++j)
               {
                   if(dp[n-1][i][j]>ret)
                       ret = dp[n-1][i][j];
               }
           }
           printf("%d\n", ret);
        }
        return 0;
    }
  • 相关阅读:
    (82)zabbix如何选择适合的监控类型
    (80)zabbix性能优化中的几个建议
    (79)zabbix key总是not supported的解决方法
    (78)zabbix值缓存(value cache)说明
    Centos7搭建docker仓库
    centos7安装docker
    Win10调整MTU值
    nginx配置ssl证书
    CentOS7.6配置do.cker和K.B.S
    RAID阵列盘有一块状态变为外来处理方法
  • 原文地址:https://www.cnblogs.com/buptLizer/p/2651881.html
Copyright © 2011-2022 走看看