[APIO2007]动物园
Posted ysner
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[APIO2007]动物园相关的知识,希望对你有一定的参考价值。
题面
\(n\leq10^5\)
解析
注意到每个小朋友只能看到\(5\)个动物,可以状压\(DP\)。
我们可以对每个小朋友预处理一下他面对每种状态会不会满意。
然后就可枚举动物数\(j\)和当前状态\(s\)进行状压\(DP\)。
\(f[j][s]=max(f[j-1][(s\&15)<<1],f[j-1][(s\&15)<<1|1])+num[j][s]\)
有点绕脑的是这是个环。
我们在开始时规定\(0\)号位(即\(n\)号位)的某一状态可以转移,最后只统计\(n\)号位上这一状态的答案即可。#include <iostream> #include <cstring> #include <cstdio> #define check(st) ((st&l)||(~st&d)) using namespace std; template <typename Tp> inline void read(Tp &x) { x=0; char ch=getchar(); while(ch<‘0‘||ch>‘9‘) ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar(); } const int maxn=50010; int n,m,ans,f[maxn][40],num[maxn][40]; inline int max(int x,int y){return x>y?x:y;} void input() { int a,b,c,l,d,t; read(n);read(m); for(int i=1;i<=m;i++) { read(a);read(b);read(c); l=d=0; for(int j=1;j<=b;j++) {read(t);t=(t-a+n)%n;l|=1<<t;} for(int j=1;j<=c;j++) {read(t);t=(t-a+n)%n;d|=1<<t;} for(int j=0;j<32;j++) if(check(j)) num[a][j]++; } } int main() { input(); for(int i=0;i<32;i++) { memset(f[0],128,sizeof(f[0])); f[0][i]=0; for(int j=1;j<=n;j++) for(int s=0;s<32;s++) f[j][s]=max(f[j-1][(s&15)<<1],f[j-1][(s&15)<<1|1])+num[j][s]; if(ans<f[n][i]) ans=f[n][i]; } printf("%d\n",ans); return 0; }
以上是关于[APIO2007]动物园的主要内容,如果未能解决你的问题,请参考以下文章