• POJ1185 炮兵阵地


    题目描述 Description

    司令部的将军们打算在N × M的网格地图上部署他们的炮兵部队。一个N × M的地图由N行M列组成,地图的每一格可能是山地(用"H"表示),也可能是平原(用"P"表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队 (山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:
    如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图 上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。 现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围 内),在整个地图区域内最多能够摆放多少我军的炮兵部队。

    输入描述 Input Description

    第一行包含两个由空格分割开的正整数,分别表示N和M;
    接下来的N行,每一行含有连续的M个字符('P'或者'H'),中间没有空格。按顺序表示地图中每一行的数据。N ≤ 100, M ≤ 10。

    输出描述 Output Description

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

    样例输入 Sample Input

    5 4
    PHPP
    PPHH
    PPPP
    PHPP
    PHHP

    样例输出 Sample Output

    6

    正解:状压DP

    解题报告:

      今天考试T4。

      这是一道状压DP裸题,我一上来就看到这道题,就知道是NOI2001原题,然而我并没有想到怎么做。因为我一直很纠结这一行的决策会受上两行的影响,所以总在想着用一个什么三进制数来表示,然而总是没想通。其实并不需要三进制,就用常规的二进制思路就可以做这道题了。我用一个二进制数S1表示放炮兵,0表示不放,显然对于每一行可以预处理一下哪些状态是可行的。位运算可以大大加速预处理速度。并且我们可以发现,一行的可行的状态数很少,而且绝对不会超过60。那么这就很好做了,我预处理出每一行的可行状态,存下来,并且算一下当前状态下的炮兵数量,每次枚举的时候我只考虑这些可行状态,就可以大大加速,避免了许多无用状态的讨论。然后,因为当前行的决策要受上两行的影响,既然要受影响,那么我不妨把状态记下来。我用f[i][S1][S2]表示第i行放状态为S1i-1行放S2的最大值。这样的话转移也很明了了,我枚举一个i-2行的状态K1,所以f[i][S1][S2]=max(f[i-1][S2][K1]+cnt[S1],f[i][S1][S2]),也就是说我每次需要枚举三个状态。显然,第一行我们需要特殊处理,直接把第一行的所有情况算出来,为了方便处理边界,我可以给第0行增加一种状态0,这样方便转移。其余的就是一些细节了,比如果S1S2K1互不冲突的判断,位运算可以随便过啦。

     

     

     1 //It is made by jump~
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <algorithm>
     8 #include <ctime>
     9 #include <vector>
    10 #include <queue>
    11 #include <map>
    12 #include <set>
    13 using namespace std;
    14 typedef long long LL;
    15 const int inf = (1<<30);
    16 const int MAXN = 1011;
    17 const int MAXM = 5000011;
    18 int n,m,ans,end;
    19 int a[MAXN][12];
    20 char ch[12];
    21 int f[MAXN][100][100];//f[i][S1][S2]表示第i行放状态为S1,i-1行放S2的最大值
    22 int dix[MAXN];
    23 int mp[MAXN][100],cnt[MAXN][100],num[MAXN];//每一行可行状态最多60种
    24 
    25 inline int getint()
    26 {
    27     int w=0,q=0; char c=getchar();
    28     while((c<'0' || c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); 
    29     while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w;
    30 }
    31 
    32 inline int get_cnt(int s){ int total=0; while(s) total+=s&1,s>>=1; return total; }
    33 
    34 inline void work(){
    35     n=getint(); m=getint();
    36     for(int i=1;i<=n;i++) {
    37     scanf("%s",ch);
    38     for(int j=0;j<m;j++) {
    39         if(ch[j]=='P') a[i][j+1]=1;
    40         else a[i][j+1]=0;
    41         dix[i]|=a[i][j+1]*(1<<j);
    42     }
    43     }
    44     end=(1<<m)-1;
    45     for(int i=1;i<=n;i++) {
    46     for(int s=0;s<=end;s++) {
    47         if(( s&(s<<1) )!=0) continue; if(( s&(s<<2) )!=0) continue;
    48         if((dix[i]&s)!=s) continue;
    49         num[i]++; mp[i][num[i]]=s; cnt[i][num[i]]=get_cnt(s);
    50     }
    51     }
    52     num[0]++; for(int i=1;i<=n;i++) for(int j=1;j<=num[1];j++) f[1][j][1]=cnt[1][j];
    53     int now,k1,k2;
    54     for(int i=2;i<=n;i++) {
    55     for(int j=1;j<=num[i-1];j++) {
    56         k1=mp[i-1][j];
    57         for(int k=1;k<=num[i-2];k++) {
    58         k2=mp[i-2][k]; if(f[i-1][j][k]==0) continue;
    59         for(int l=1;l<=num[i];l++) {
    60             now=mp[i][l]; if((now&k1)!=0) continue; if((now&k2)!=0) continue;
    61             f[i][l][j]=max(f[i][l][j],f[i-1][j][k]+cnt[i][l]);
    62         }
    63         }
    64     }
    65     }
    66     for(int i=1;i<=num[n];i++) for(int j=1;j<=num[n-1];j++) ans=max(ans,f[n][i][j]);
    67     printf("%d",ans);
    68 }
    69 
    70 int main()
    71 {
    72     work();
    73     return 0;
    74 }

     

     

  • 相关阅读:
    【Css】SCSS基本语法
    【Css】Scss 与 Sass 简单示例
    【移动端】cordova在app中打开外部链接——cordova-plugin-inappbrowser
    border-radius圆角边框属性讲解
    css 设置 transform 无效
    linux下设置php执行命令
    linux下php命令无法使用如何解决
    微信小程序 --- 表单输入验证(手机号、邮箱验证、输入非空)
    微信小程序倒计时组件开发
    小程序--三级联动
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5930741.html
Copyright © 2020-2023  润新知