zoukankan      html  css  js  c++  java
  • poj1185 炮兵阵地【状压DP】

    炮兵阵地
    Time Limit: 2000MS   Memory Limit: 65536K
    Total Submissions: 32802   Accepted: 12650

    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 4
    PHPP
    PPHH
    PPPP
    PHPP
    PHHP

    Sample Output

    6

    Source

     
    题意:
    有一个n*m的格子有的格子是山,有的格子是平原。只有平原可以放一个炮兵。炮兵的攻击范围是两格,也就是说如果一个格子放了炮兵,他上下左右两格里不能再放炮兵。问这样n*m的地图中,可以最多放多少炮兵。
     
    思路:
    因为m是小于10的,每个格子又只有放或者不放的状态。所以我们可以考虑状压。用一个十进制数来表示某一行的放炮兵状态。第j位是1表示第j列的格子放了炮兵,0表示没有放。同理,地图上一行的山或是平原的状态也可以用十进制数来表示。
    以行数i作为状态转移的阶段,转移的时候需要看的是前面两行的状态。用dp[i][j][k]表示第i行的状态时j,第i-1行的状态是k时,前i行最多的炮兵数。
    显然dp[i][j][k] = max(dp[i -1][k][l]) + j的二进制表示中1的个数
    并且并不是所有0~2^m-1的数都是可行的,必须要是二进制中1之间的间隔大于等于2的数才可以。
    那么我们就可以首先预处理出所有可行的数,每次遍历这些数就可以了。对于每一行还需要去判断一下是否满足当前的地图状态。
    刚开始用把平原当1,山当0,这样判断的时候位运算会有点麻烦。所以后面改成了用山当1,这样只需要用& == 0就可以了。
    debug了超级久,今天终于找到bug了,太菜了。码力堪忧......
      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <algorithm>
      4 #include <cmath>
      5 #include <cstring>
      6 
      7 using namespace std;
      8 typedef long long LL;
      9 #define inf 0x3f3f3f3f
     10 
     11 const int maxn = 105;
     12 int n, m, mostm;
     13 int dp[maxn][80][80], dixing[maxn];
     14 int cntone[80], S[80], cnt;
     15 
     16 bool valid(int i, int x)
     17 {
     18     if (dixing[i] & x)return false;
     19     else return true;
     20 }
     21 
     22 int get_one(int x)
     23 {
     24     int res = 0;
     25     while (x) {
     26         res += (x & 1);
     27         x >>= 1;
     28     }
     29     return res;
     30 }
     31 
     32 bool ok(int x)
     33 {
     34     if (x & (x << 1))return false;
     35     if (x & (x << 2)) return false;
     36     return true;
     37 }
     38 
     39 void getS()
     40 {
     41     cnt = 0;
     42     mostm = 1 << m;
     43     for (int i = 0; i < mostm; i++) {
     44         if (ok(i)) {
     45             S[cnt] = i;
     46             cntone[cnt] = get_one(i);
     47             cnt++;
     48         }
     49     }
     50 }
     51 
     52 int main()
     53 {
     54     while (scanf("%d%d", &n, &m) != EOF) {
     55         getS();
     56         memset(dixing, 0, sizeof(dixing));
     57         for (int i = 1; i <= n; i++) {
     58             char tmp[20];
     59             scanf("%s", tmp);
     60             //printf("%s", tmp + 1);
     61             for (int j = 0; j < m; j++) {
     62                 //cout<<tmp[j]<<endl;
     63                 if (tmp[j] == 'H') {
     64                     dixing[i] |= (1 << (m - 1 - j));
     65                 }
     66             }
     67         }
     68 
     69         memset(dp, -1, sizeof(dp));
     70         dp[0][0][0] = 0;
     71         int ans = 0;
     72         for (int j = 0; j < cnt; j++) {
     73             if (valid(1, S[j])) {
     74                 dp[1][j][0] = cntone[j];
     75                 ans = max(ans, dp[1][j][0]);
     76             }
     77         }
     78         //cout<<1<<" "<<ans<<endl;
     79 
     80         for (int i = 2; i <= n; i++) {
     81             int tiaoshi = -1;
     82             for (int j = 0; j < cnt; j++) {
     83                 if (valid(i, S[j])) {
     84                     for (int k = 0; k < cnt; k++) {
     85                         if (valid(i - 1, S[k]) && (S[j] & S[k]) == 0) {
     86                             int mmm = -1;
     87                             for (int l = 0; l < cnt; l++) {
     88                                 if (valid(i - 2, S[l]) && dp[i - 1][k][l] != -1 && (S[j] & S[l]) == 0) {
     89                                     mmm = max(mmm, dp[i - 1][k][l]);
     90                                 }
     91                             }
     92                             //cout<<i - 1<<" "<<mmm<<endl;
     93                             dp[i][j][k] = max(dp[i][j][k], mmm + cntone[j]);
     94                             tiaoshi = max(tiaoshi, dp[i][j][k]);
     95                             if (i == n)ans = max(ans, dp[i][j][k]);
     96                         }
     97                     }
     98                 }
     99             }
    100             //cout<<i<<" "<<tiaoshi<<endl;
    101         }
    102         printf("%d
    ", ans);
    103     }
    104 
    105     //return 0;
    106 }
  • 相关阅读:
    chrome被篡改 导航到搜狗 或者特殊页面
    安装tomcat jdk
    监控tomcat 启动
    关于如何关闭445端口
    python模拟大数据登陆
    搭建vsftpd服务
    kali syn洪水攻击实例
    HP880G3 安装RHEL6.5
    Python_列表
    Python第一个请求接口
  • 原文地址:https://www.cnblogs.com/wyboooo/p/9796829.html
Copyright © 2011-2022 走看看