• [NOI2001] 炮兵阵地 题解


    题目链接

    题目描述


     

    司令部的将军们打算在 N×M 的网格地图上部署他们的炮兵部队。

    一个N×M 的地图由 N 行 M 列组成,地图的每一格可能是山地(用 H 表示),也可能是平原(用 P 表示),如下图。

    在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:

    如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。

    图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。

    现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。

    输入格式

    第一行包含两个由空格分割开的正整数,分别表示 N 和 M

    接下来的 N 行,每一行含有连续的 M 个字符,按顺序表示地图中每一行的数据。

    输出格式

    一行一个整数,表示最多能摆放的炮兵部队的数量。

    输入输出样例

    输入 #1

       5 4

    PHPP
    PPHH
    PPPP
    PHPP
    PHHP

    输出 #1

    6

    数据范围

    N100,M10

     

    题解


    挺简单的,容易发现基于连通性的状压dp套路基本相同

    这道题可以看做是玉米田拿到题的升级版(十字多延伸了)

    既然延伸到了前两行,状态转移的时候也需要考虑前两行的状态

    由于这道题空间限制比较小,如果按照常规开数组的话应该会超1亿,肯定会爆空间

    所以我们考虑用滚动数组来优化空间,其他注意的地方和之前做的题差不多,没啥好说的

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    
    using namespace std;
    
    const int N = 1010;
    const int M = 1 << 10;
    int f[2][M][M];
    int cnt[M];
    int g[N];
    vector<int> state;
    
    int n,m;
    bool check(int x)
    {
        for(int i = 0; i < m; ++ i)
        {
            if((x >> i & 1) && ((x >> i + 1 & 1) || (x >> i + 2 & 1))) return false;
        }
        return true;
    }
    
    
    int count(int x)
    {
        int res = 0;
        for(int i = 0; i < m; ++ i) res += x >> i & 1;
        return res;
    }
    
    int main()
    {
        cin >> n >> m;
        for(int i = 1; i <= n; ++ i)
          for(int j = 0; j < m; ++ j)
            {
                char t;
                cin >> t;
                if(t == 'H') g[i] += 1 << j;
            }
            
        for(int i = 0; i < 1 << m; ++ i)
         if(check(i))
         {
             cnt[i] = count(i);
             state.push_back(i);
         }
         
         
        for(int i = 1; i <= n; ++ i)
         for(int j = 0; j < state.size(); ++ j)
            for(int k = 0; k < state.size(); ++ k)
              for(int u = 0; u < state.size(); ++ u)
              {
                  int a = state[j],b = state[k],c = state[u];
                  if(a & b | a & c | b & c) continue;
                  if(g[i] & b | g[i - 1] & a) continue;
                  f[i & 1][j][k] = max(f[i & 1][j][k],f[i - 1 & 1][u][j] + cnt[b]);
              }
        int res = 0;
        for(int i = 0; i < state.size(); ++ i)
          for(int j = 0; j < state.size(); ++ j)
             res = max(res,f[n & 1][i][j]);
             
        cout << res << endl;
        return 0;
    }
     
  • 相关阅读:
    阿里云如何打破Oracle迁移上云的壁垒
    第三代DRDS分布式SQL引擎全新发布
    玩转MaxCompute studio SQL编辑器
    如何在阿里云上安全的存放您的配置
    阿里云E-HPC联合安世亚太、联科集团共建云超算生态
    阿里云弹性裸金属服务器-神龙架构(X-Dragon)揭秘
    从保障淘宝到全球市场“第一阵营”,阿里云的DDoS防护之路走了多远?
    飞天技术汇“2018云栖大会·上海峰会”专场,等你加入
    Yeoman:Web 应用开发流程与工具—AngularJS—Bootstrap—js
    【codeforces 550A】Two Substrings
  • 原文地址:https://www.cnblogs.com/yjyl0098/p/14631006.html
Copyright © 2020-2023  润新知