【刷题】【状压dp】动物园

找出与状态转移有关的量,并且保证无后效性,

这道题可以找到移动区间的角度,简单有效的设计出状态,列出方程,

因为不可能去每个m(m<=5*10^4),找一个5,

所以我们在输入的时候,把数据处理成每个起始点的状态,

然后把每个状态设计成起始点,5个单位的区间,是否还有动物的状态,

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring> 
using namespace std;
inline int read()
{
    int x=0;char c=getchar();
    while(c<'0' || c>'9') c=getchar();
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar();
    return x;
}
int n,m,ans;
const int N=10003,Mx=1<<5;
int val[N][Mx],f[N][Mx];

int main()
{
    n=read(),m=read();
    int p,fail,like,F,L,xx;
    for(int i=1;i<=m;i++)
    {
        p=read(),fail=read(),like=read();
        F=L=0;
        for(int j=1;j<=fail;j++)
        {
            xx=read();
            F|=(1<<((p+4-xx)%n));
        }
        for(int j=1;j<=like;j++)
        {
            xx=read();
            L|=(1<<((p+4-xx)%n));
        }
        for(int j=0;j<Mx;j++) 
            if( (j&L) || ((~j)&F) ) 
                val[p][j]++;
    }
    
    //先是第一个状态,然后往后面加0/1 
    for(int i=0;i<Mx;i++)
    {
        memset(f,128,sizeof(f));
        f[0][i]=0;
        
        for(int j=1;j<=n;j++)
            for(int s=0;s<Mx;s++) 
                f[j][s]=max(f[j-1][s>>1],f[j-1][(s>>1)+16]) +val[j][s];
        
        ans=max(ans,f[n][i]);
    }
    
    printf("%d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/xwww666666/p/11708894.html