分析
本题对于 (n) 和 (c) 的范围都比较大,不好直接处理,但是每个人可以看到的围栏数量只有 (5) 我们可以从这里入手考虑
设 (dp[i][s]) 表示对于 (i,i+1,i+2,i+3,i+4) 这 (5) 个围栏的动物情况为 (s) 时的最大开心人数
那么转移即为:
[dp[i][s]= max(dp[i-1][((s&15)<<1)|1],dp[i-1][(s&15)<<1])+sum[i][s]
]
其中 (sum[i][s]) 表示第 (i,i+1,i+2,i+3,i+4) 个围栏中动物情况为 (s) 的开心人数
而 ((s&15)<<1|1) 与 ((s&15)<<1) 则表示第 (i-1,i,i+1,i+2,i+3) 个围栏中的动物情况
对于 (sum) 数组的处理,我们考虑题目中的条件:
- 至少有一个他害怕的动物被移走
- 至少有一个他喜欢的动物没被移走
那么我们可以在输入的时候处理出每个人对于某个围栏的喜爱情况,即为 (dislike) 和 (like) , 其含义与 (dp[i][s]) 中的 (s) 的含义相同
我们可以枚举围栏中的动物情况 (j) ,则:
if((j&dislike)||(~j&like)) sum[i][j]++;
code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<math.h>
#include<queue>
#define ll long long
inline ll read()
{
ll x=0,f=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch))
{
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
return x*f;
}
const ll maxn=5e4+10;
const ll maxm=1e4+10;
const ll inf=1e9+7;
ll n,c,ans;
ll E,F,L,X,Y;
ll sum[maxn][(1<<5)+10];
ll dp[maxm][(1<<5)+10];
int main(void)
{
n=read(),c=read();
for(int i=1;i<=c;i++)
{
E=read(),F=read(),L=read();
ll dlik=0,lik=0;
for(int j=1;j<=F;j++)
{
scanf("%lld",&X);
X=(X-E+n)%n;
dlik|=1<<X;
}
for(int j=1;j<=L;j++)
{
scanf("%lld",&Y);
Y=(Y-E+n)%n;
lik|=1<<Y;
}
for(int j=0;j<(1<<5);j++)
{
if((j&dlik)||(~j&lik)) sum[E][j]++;
}
}
for(int i=0;i<32;i++)
{
for(int j=0;j<32;j++) dp[0][j]=-inf;
dp[0][i]=0;
for(int j=1;j<=n;j++)
{
for(int k=0;k<32;k++)
{
dp[j][k]=std::max(dp[j-1][((k&15)<<1)|1],dp[j-1][(k&15)<<1])+sum[j][k];
}
}
ans=std::max(ans,dp[n][i]);
}
printf("%lld
",ans);
return 0;
}