【NOI2001】炮兵阵地

  • 本文为博主原创,未经许可不得转载

这题好神,不看题解根本想不起来

用f[i][j][k]表示第i行状态为j,前一行状态为k的答案

则f[i][j][k]=max{f[i-1][k][l]}

至于如何判断状态是否合法,细节较多,详见代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<bits/stdc++.h>
#define FILE "read"
#define cmin(a,b) a=min(a,b)
#define cmax(a,b) a=max(a,b)
using namespace std;
int n,m,ans,cnt,vst[110],sum[110],check[110],f[110][110][110];
char ch[110][20];
inline int read(){
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
int get(int x){int temp(0);while(x)temp+=(x&1),x>>=1;return temp;}
bool judge(int x){return (!(x&(x<<1)))&&(!(x&(x<<2)));}
int main(){
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
n=read(); m=read(); memset(f,-1,sizeof(f));
for(int i=1;i<=n;++i) scanf("%s",ch[i]+1);
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j)
if(ch[i][j]=='H') check[i]|=(1<<(j-1));
for(int i=0;i<(1<<m);++i)if(judge(i))vst[++cnt]=i,sum[cnt]=get(i);
for(int i=1;i<=cnt;++i)if(!(check[1]&vst[i]))f[1][i][1]=sum[i];
for(int i=1;i<=n;++i)for(int j=1;j<=cnt;++j)if(!(check[i]&vst[j])){
for(int k=1;k<=cnt;++k)if(!(vst[j]&vst[k])){
for(int l=1;l<=cnt;++l)if(!(vst[j]&vst[l])){
if(f[i-1][k][l]!=-1) cmax(f[i][j][k],f[i-1][k][l]+sum[j]);
}
}
}
for(int i=1;i<=cnt;++i)for(int j=1;j<=cnt;++j)cmax(ans,f[n][i][j]);
printf("%d\n",ans);
}
文章目录
,