• 【POJ1185】炮兵阵地 状压DP


    感觉总是被一些SB错误所困扰。。。

    差不多还是(模板题)注意数组空间的大小,和对于合法状态的判断。

    f[i][j][k]=max(f[i][k][j],f[i-1][l][k]+num[j]) (f[i][j][k]表示:第i行状态为k且满足第i-1行状态为j的合法方案数,num[i]是状态i所包含的方案数)

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 using namespace std;
     6 #define N 110
     7 #define M 70
     8 #define inf 0x7fffffff
     9 int map[N],can[M],num[N];
    10 int   dp[N][M][M];
    11 int n,m,T,cnt,ans;
    12 bool ju1(int x)
    13 {
    14     if ((x&(x<<1)) || (x&(x<<2))) return false;
    15     return true;
    16 }
    17 bool ju2(int x,int y)
    18 {
    19     return map[x]&can[y];
    20 }
    21 int count(int x)
    22 {
    23     int sum=0;
    24     while (x)
    25     {
    26         if (x&1) sum++;
    27         x>>=1;
    28     }
    29     return sum;
    30 }
    31 int main()
    32 {
    33     //scanf("%d",&T);
    34     char s;
    35     while (~scanf("%d%d",&n,&m))
    36     {
    37         //scanf("%d%d",&n,&m);
    38         memset(dp,-1,sizeof(dp));
    39         memset(map,0,sizeof(map));
    40         memset(can,0,sizeof(can));
    41         memset(num,0,sizeof(num));
    42         ans=-inf;
    43         cnt=0;
    44         for (int i=1;i<=n;i++)
    45         {
    46             getchar();
    47             for (int j=1;j<=m;j++)
    48             {
    49                 scanf("%c",&s);
    50                 if (s=='H') map[i]+=(1<<(j-1));    
    51             }
    52         }
    53         for (int i=0;i<(1<<m);i++)
    54             if (ju1(i)) can[++cnt]=i;
    55         for (int i=1;i<=cnt;i++)
    56         {
    57             num[i]=count(can[i]);
    58             if (!ju2(1,i))    dp[1][1][i]=num[i];
    59         }
    60         for (int i=2;i<=n;i++)//line
    61         {
    62             for (int j=1;j<=cnt;j++)//now
    63             {
    64                 if (ju2(i,j)) continue;
    65                 for (int k=1;k<=cnt;k++)// before last
    66                 {
    67                     if (can[j]&can[k]) continue;
    68                     for (int l=1;l<=cnt;l++) //last
    69                     {
    70                         if (can[l]&can[j]) continue;
    71                         if (dp[i-1][k][l]==-1) continue;
    72                         dp[i][l][j]=max(dp[i][l][j],dp[i-1][k][l]+num[j]);    
    73                         //ans=max(ans,dp[i][l][j]);
    74                     }
    75                 }
    76             }
    77         }
    78         for (int i=1;i<=cnt;i++)
    79             for (int j=1;j<=cnt;j++)
    80                 ans=max(ans,dp[n][i][j]);
    81     printf("%d
    ",ans);
    82     }
    83     return 0;
    84 }
    View Code

    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

    —Anime Otaku Save The World.
  • 相关阅读:
    iphone6闪存检测
    knowledges address
    类linux系统/proc/sysrq-trigger文件功能作用
    iphone 6s pp助手 越狱
    C pointers
    ubuntu15.04 TLS
    ubuntu cenots 禁止本地登陆
    CentOS7
    CentOS7安全设置 yum-cron系统自动更新,firewalld防火墙简单使用
    SAS学习笔记之函数应用
  • 原文地址:https://www.cnblogs.com/DMoon/p/5336100.html
Copyright © 2020-2023  润新知