洛谷P2704 [NOI2001]炮兵阵地

版权声明:我这么弱的蒟蒻,虽然博文不是很好,但也请标明转发地址喵! https://blog.csdn.net/ACerAndAKer/article/details/82806372

裸状压

正常状压只需要枚举上一行即可,但是这道题我们需要枚举上两行,这样才能保证不冲突,合法的状态时i&(i<<1)=0,i&(i<<2)=0,我们只需要考虑它和他左边不冲突就好了,右边会有下一个位置保证和他不冲突,于是这道题就没了,需要滚动一下数组

代码

//By AcerMo
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m;
char map[105][105];
int e[1050],s[1050],t[1050],f[2][1050][1050],cnt;
inline void dfs()
{
	int su=1<<m;
	for (int i=0;i<su;i++)
	if (!(i&(i<<1))&&!(i&(i<<2))) 
	{
		s[++cnt]=i;int k=i;
		while (k) t[cnt]+=(k&1),k>>=1;
	}
	return ;
}
inline bool che(int x,int y)
{
	return (s[x]&e[y])==0;
}
signed main()
{
	scanf("%d%d",&n,&m);dfs();
	for (int i=1;i<=n;i++) scanf("%s",map[i]+1);
	for (int i=1;i<=n;i++)
	for (int k=1;k<=m;k++)
	if (map[i][k]=='H') e[i]+=(1<<(m-k));
	int x=1,y=0;
	for (int i=1;i<=cnt;i++)
	if (che(i,1)) f[x][i][1]=t[i];	 
	swap(x,y);
	for (int i=1;i<=cnt;i++)
	if (che(i,2))
	for (int k=1;k<=cnt;k++)
	if (che(k,1)&&!(s[i]&s[k]))
	f[x][i][k]=t[i]+t[k];
	for (int i=3;i<=n;i++)
	{
		swap(x,y);
		for (int k=1;k<=cnt;k++)
		if (che(k,i))
		for (int j=1;j<=cnt;j++)
		if (!(s[k]&s[j])&&che(j,i-1))
		for (int h=1;h<=cnt;h++)
		if (!(s[h]&s[j])&&!(s[h]&s[k])&&che(h,i-2))
		f[x][k][j]=max(f[x][k][j],f[y][j][h]+t[k]);
	}
	int ans=0;
	for (int i=1;i<=cnt;i++)
	for (int k=1;k<=cnt;k++)
	ans=max(ans,f[x][i][k]);
	cout<<ans;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/ACerAndAKer/article/details/82806372