题意:一开始棋盘上布满蜘蛛,可以安排每个蜘蛛想邻近的四个方向走,一秒走一次,问一秒以后空格最多有多少。
做法:暴力枚举一下每一列蜘蛛的运动方向,可以用状态压缩确定每一行的蜘蛛在一秒之后的状况,这里值得判断的是每个状态是否可以存在假设a,b,c为相邻的三行
只有当(b|b>>1|b<<1|a|c&(lim-1))==lim,b(>>1<<1是不是很像左右移动)才是可以存在的,不存在的也就是第一行的上一层就只有0这个状态存在一开始居然没有
/******
看见这么小的规模,
就要想到用状态压缩啊。
影响最多只有两行
注意判断状态是否存在的方法
*********/
#include<cstdio>
#include<algorithm>
#include<cstring>
#define eps -1e8
using namespace std;
const int LMT=1<<6;
int dp[45][LMT][LMT],get[LMT],n,m,lim;
bool check(int a,int b,int c)
{
int x=b|(b<<1)|(b>>1)|a|c;
return (x&(lim-1))==(lim-1);
}
int work(int x)
{
int res,l;res=l=0;
do
if(x&1)res++;
while(x>>=1);
return m-res;
}
void init(void)
{
for(int i=0;i<=n+1;i++)
for(int j=0;j<LMT;j++)
for(int k=0;k<LMT;k++)
dp[i][j][k]=eps;
for(int i=0;i<LMT;i++)get[i]=work(i);
for(int i=0;i<lim;i++)dp[0][0][i]=0;
}
int main(void)
{
int ans=0;
scanf("%d%d",&n,&m);
if(n<m)
{
int t=n;n=m;m=t;
}
lim=1<<m;
init();
for(int i=0;i<n;i++)
for(int j=0;j<lim;j++)
for(int k=0;k<lim;k++)
if(dp[i][j][k]!=eps)
for(int l=0;l<lim;l++)
if(check(j,k,l))dp[i+1][k][l]=max(dp[i+1][k][l],dp[i][j][k]+get[k]);
for(int j=0;j<lim;j++)ans=max(ans,dp[n][j][0]);
printf("%d\n",ans);
return 0;
}
&lim-1失败