注:poj代码放在https://www.luogu.org/paste/oofcjs7e
有点坑,数据点
1
1
1
1
1
1
P
P
P搞不了(也就是说下面的代码非正解(正解还得搞一搞,上面的网址))
然后还有ssl 1384和jzoj 1768(没位置放标签了)
题目
在一个地图有平原也有山地,可以在平原放炮兵,攻击范围是一个边长为2( i i i(炮兵)到 i i i+2)的十字,炮兵不能相互攻击,问最多能摆放多少个炮兵
分析
用一个二进制数
x
x
x表示第
i
i
i行的炮兵状态,集合
S
S
S为二进制相邻1的距离不少于3的数(最多60个),设
c
n
t
(
x
)
cnt(x)
cnt(x)为在二进制下1的个数,
p
d
(
i
,
x
)
pd(i,x)
pd(i,x)为炮兵的位置属于平原,且
x
x
x属于
S
S
S集合a,预处理后开始动态规划,设
f
[
n
]
[
j
]
[
k
]
f[n][j][k]
f[n][j][k]表示第
n
n
n行的状态为
j
j
j,第
n
−
1
n-1
n−1行状态为
k
k
k,前n行的最多摆放炮兵的数量
f
[
n
]
[
j
]
[
k
]
=
m
a
x
{
f
[
n
−
1
]
[
k
]
[
l
]
+
c
n
t
(
j
)
}
f[n][j][k]=max\{f[n-1][k][l]+cnt(j)\}
f[n][j][k]=max{f[n−1][k][l]+cnt(j)}(
j
j
j and
k
k
k=0,$j $and
l
l
l=0,
k
k
k and
l
l
l=0,pd(n,j),pd(n-1,k),pd(n-2,l)),否则为0
代码
#include <cstdio>
#include <vector>
#include <cstring>
const int make[10]={1,2,4,9,18,36,73,146,292,595};
struct rec{int x,y;}; std::vector<rec>vec;
int n,m,f[3][61][61],nap[101],ans;
int in(){
int ans=0; char c=getchar();
while (c<48||c>57) c=getchar();
while (c>47&&c<58) ans=ans*10+c-48,c=getchar();
return ans;
}
int max(int a,int b){return (a>b)?a:b;}
int main(){
n=in(); m=in(); int x=0;
for (register int i=1;i<=n;i++){
char c=getchar();
while (c<65||c>90) c=getchar(); if (c=='H') nap[i]|=1<<m-1;
for (register int j=1;j<m;j++) nap[i]|=getchar()=='H'?(1<<m-j-1):0;
}
for (register int i=0;i<=make[m-1];i++){
bool flag=0;
for (register int j=0;j<m-1&&!flag;j++) if ((i&(1<<j))&&(i&(1<<j+1))) flag=1;
if (flag) continue;
for (register int j=0;j<m-2&&!flag;j++) if ((i&(1<<j))&&(i&(1<<j+2))) flag=1;
if (!flag) {
rec c; c.x=i; c.y=0;
for (register int j=0;j<m;j++) c.y+=i>>j&1;
vec.push_back(c);
}
}
for (register int i=0;i<vec.size();i++)
if (!(vec[i].x&nap[1])) f[1][i][vec.size()]=vec[i].y;
for (register int i=0;i<vec.size();i++)
if (!(vec[i].x&nap[2])){
for (register int j=0;j<vec.size();j++)
if (!(vec[j].x&nap[1])&&!(vec[i].x&vec[j].x))
f[2][i][j]=max(f[2][i][j],f[1][j][vec.size()]+vec[i].y);
}
for (register int p=3;p<=n;p++){
memset(f[x],0,sizeof(f[x]));
for (register int i=0;i<vec.size();i++){
if (vec[i].x&nap[p]) continue;
for (register int j=0;j<vec.size();j++){
if (vec[j].x&nap[p-1]||vec[j].x&vec[i].x) continue;
for (register int k=0;k<vec.size();k++){
if (vec[k].x&nap[p-2]||vec[j].x&vec[k].x||vec[i].x&vec[k].x) continue;
if (p<n) f[x][i][j]=max(f[x][i][j],f[(x+2)%3][j][k]+vec[i].y);
else ans=max(ans,f[(x+2)%3][j][k]+vec[i].y);
}
}
}
x=(x+1)%3;
}
return !printf("%d",ans);
}