Codeforces Beta Round #85 (Div. 1 Only), problem: (C) Petya and Spiders 状态压缩

111C - Petya and Spiders

题意:一开始棋盘上布满蜘蛛,可以安排每个蜘蛛想邻近的四个方向走,一秒走一次,问一秒以后空格最多有多少。

做法:暴力枚举一下每一列蜘蛛的运动方向,可以用状态压缩确定每一行的蜘蛛在一秒之后的状况,这里值得判断的是每个状态是否可以存在假设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失败


你可能感兴趣的:(Codeforces Beta Round #85 (Div. 1 Only), problem: (C) Petya and Spiders 状态压缩)