题面
题意
给出一张地图,上面一些点可以放置炮兵,要求与炮兵在同一行或同一列的炮兵与它的距离都大于2,问:最多可以在图上放几个炮兵。
地图大小:10*100.
做法
从数据范围上不难发现要用状压dp来做,因为炮兵“攻击范围”是2,因此要状压2行,这样复杂度为至少为O(2^10^2*100)肯定会T,因此必须要优化。
可以发现,可以在转移时只考虑在行上合法的状态,只要当有10列时也只有60种,因此只要预处理出行上那些状态是合法的,一行行转移即可得到答案。
代码
#include<iostream>
#include<cstdio>
#define N 110
#define M 1100
using namespace std;
int n,m,hf[N],val[N],mm[N],dp[N][N][N],cnt,ans;
char str[N];
int main()
{
int i,j,k,t;
cin>>m>>n;
for(i=0;i<(1 << n);i++)
{
if(i&(i>>1)||i&(i>>2)) continue;
hf[++cnt]=i;
for(j=i;j;j>>=1) val[cnt]+=j&1;
}
for(i=1;i<=m;i++)
{
scanf("%s",str+1);
for(j=1;j<=n;j++)
{
if(str[j]=='H')
mm[i]|=(1 << (j-1));
}
}
for(i=1;i<=m;i++)
{
for(j=1;j<=cnt;j++)
{
if(mm[i]&hf[j]) continue;
for(k=1;k<=cnt;k++)
{
if(hf[k]&hf[j]) continue;
for(t=1;t<=cnt;t++)
{
if(hf[t]&hf[j] || hf[t]&hf[k]) continue;
dp[i][k][j]=max(dp[i][k][j],dp[i-1][t][k]+val[j]);
ans=max(ans,dp[i][k][j]);
}
}
}
}
cout<<ans;
}