zoukankan      html  css  js  c++  java
  • [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;
    }
     
  • 相关阅读:
    149. Max Points on a Line(js)
    148. Sort List(js)
    147. Insertion Sort List(js)
    146. LRU Cache(js)
    145. Binary Tree Postorder Traversal(js)
    144. Binary Tree Preorder Traversal(js)
    143. Reorder List(js)
    142. Linked List Cycle II(js)
    141. Linked List Cycle(js)
    140. Word Break II(js)
  • 原文地址:https://www.cnblogs.com/yjyl0098/p/14631006.html
Copyright © 2011-2022 走看看