TwilightSparkle @ 2021-11-15 22:45:24
#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<queue>
#define R register int
using namespace std;
const int maxn=105;
const int maxm=12;
//DP:所有已经摆完前i行,且i-1行状态为j,第i行状态为k的max
//不一样的点:第i-2行 (第i行为k,第i-1行为j)
//条件:(a&b)|(a&c)|(b&c)==0--无交集
//2:(g[i-1]&a)|(g[i]&b)==0--炮再平地(不能放的于a,b,无交集)
int dp[2][1<<maxm][1<<maxm];//已经摆完前i-1行,第i-1行状态为j的max
//滚动数组小技巧:&1,因为&1将奇偶交替转换成了01交替,很好用
int g[maxn];
int n,m;
int cnt[1<<maxm];
vector<int> ok;
inline int read()//有inline 不写返回类型,真是嫌命长!
{
int f=1,x=0;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
f*=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<3)+(x<<1)+(ch^48);
ch=getchar();
}
return x*f;
}
inline bool check(int state)
{
for(R i=0;i<m;i++)
if(((state>>i)&1)&&(((state>>(i+1))&1)||((state>>(i+2)&1))))//相邻两个1之间至少隔两块空地
return 0;
return 1;
}
inline int count(int state)
{
int cnt=0;
for(R i=0;i<m;i++)
{
cnt+=(state>>i)&1;//1的个数(先右移i位看是不是1,再与1判断数量)
}
return cnt;
}
int main()
{
n=read(),m=read();
for(R i=1;i<=n;i++)
{
for(R j=0;j<m;j++)
{
char c;
c=getchar();
if(c=='H')
g[i]+=1<<j;//位运算,二进制中不能放的表示为1
}
getchar();
}
/*-------预处理合法状态-------*/
for(R i=0;i<(1<<m);i++)
{
if(check(i))
{
ok.push_back(i);
cnt[i]=count(i);
}
}
/*----枚举合法状态-----*/
for(R i=1;i<=n+2;i++)
{
for(R j=0;j<ok.size();j++)
{
for(R k=0;k<ok.size();k++)
{
for(R u=0;u<ok.size();u++)
{
int a=ok[j],b=ok[k],c=ok[u];
if((a&b)||(b&c)||(a&c))
continue;
if((g[i-1]&a)||(g[i]&b))
continue;
dp[i&1][j][k]=max(dp[i&1][j][k],dp[(i-1)&1][u][j]+cnt[b]);
}
}
}
}
int ans=dp[(n+2)&1][0][0]
printf("%d\n",ans);
return 0;
}
本地输出:6。
洛谷评测反馈:Wrong Answer on line 1 column 1,read 7,expected 6。