NKOJ P1184【NOI2001 Day2 T2】炮兵阵地 (状压DP)

司令部的将军们打算在 的网格地图上部署他们的炮兵部队。一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图。


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

输入格式

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

输出格式

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

样例输入

5 4
PHPP
PPHH
PPPP
PHPP
PHHP

样例输出

6


来源  NOI2001
 
 
关于此状态后效性的问题:
若定义f[i][j] i 行状态为j 
枚举i-1 行的最优和 i-2 行的最优不是能互推的 有后效性
但是 f[i][j][k] i行 状态 j     i-1行 状态 k  f[i-1][k][o] 状态一定 只用加1 个变量 所以无后效性
 
 
code:
 1 //
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 using namespace std;
 6 int f[101][80][80];
 7 int mapp[202];
 8 int tot;
 9 int n,m;
10 int now[101];
11 int all;
12 int ans=0;
13 void dp()
14 {
15     int sum=0;
16     for(int i=1;i<=n;i++)
17        for(int j=1;j<=tot;j++)
18        {
19                if(((mapp[j]&now[i])==mapp[j])&&(((mapp[j]<<1)&mapp[j])==0)&&(((mapp[j]<<2)&mapp[j])==0))
20               {
21                     sum=0;
22                    for(int z=1;z<=m;z++)
23                   {
24                        if(mapp[j]&(1<<z-1))
25                       {
26                        sum++;
27                    }
28                }
29                    for(int k=1;k<=tot;k++)
30                   {
31                            if(((mapp[k]&mapp[j])==0)&&((now[i-1]&mapp[k])==mapp[k]))
32                            {
33                                for(int o=1;o<=tot;o++)
34                                {
35                                    if(((mapp[j]&mapp[o])==0)&&(f[i-1][k][o]+sum>f[i][j][k]||(f[i][j][k]==-1)))
36                                     f[i][j][k]=f[i-1][k][o]+sum;
37                                }
38                     }
39                }
40            }
41        }
42     
43 }
44 
45 int main()
46 {
47     cin>>n>>m;
48     char x;
49     all=(1<<m)-1;
50     for(int i=1;i<=n;i++)
51     for(int j=1;j<=m;j++)
52     {
53         cin>>x;
54         if(x=='P')
55         {
56             now[i]|=(1<<m-j);
57         }
58     }
59     memset(f,-1,sizeof(f));
60     
61     for(int i=0;i<=all;i++)
62     {
63         if((i&(i<<2))==0&&(((i&(i<<1))==0)))
64         {
65             mapp[++tot]=i;
66         }
67     }
68     f[0][1][1]=0;
69     dp();
70     for(int i=1;i<=tot;i++)
71     for(int k=1;k<=tot;k++)
72     {
73         ans=max(ans,f[n][i][k]);
74     }
75     printf("%d",ans);
76 }
刀剑映出了战士的心。而我的心,漆黑且残破
原文地址:https://www.cnblogs.com/OIEREDSION/p/11183915.html