APIO2007 洛谷P3622 动物园
题目传送门:https://www.luogu.org/problemnew/show/P3622
题解:首先,对于每个小朋友,对他有影响的只有能看到的5个点,故想到状压。
变量声明:num[i][j]:第[i,i+4]有状态为j的满足人数
状态转移方程:f[i][j]=max(f[i-1][(j&15)<<1],f[i-1][(j&15)<<1|1])+num[i][j]//取出前4个,枚举第i-1个是否有取
要注意,因为原题是一个环,故到n的状态要与初始状态相同。
代码如下:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define MN 50005 5 using namespace std; 6 int n,m,num[MN][40],f[MN][40],ans; 7 void init() 8 { 9 10 scanf("%d%d",&n,&m); 11 for(int i=1;i<=m;i++){ 12 int a,b,c,l=0,d=0,t; 13 scanf("%d%d%d",&a,&b,&c); 14 for(int j=1;j<=b;j++){ 15 scanf("%d",&t); 16 t=(t-a+n)%n; 17 l|=1<<t; 18 } 19 for(int j=1;j<=c;j++){ 20 scanf("%d",&t); 21 t=(t-a+n)%n; 22 d|=1<<t; 23 } 24 for(int j=0;j<32;j++) 25 if((j&l)||(~j&d)) num[a][j]++; 26 } 27 } 28 void solve(){ 29 for(int i=0;i<32;i++){ 30 memset(f[0],128,sizeof(f[0])); 31 f[0][i]=0; 32 for(int j=1;j<=n;j++) 33 for(int k=0;k<32;k++) 34 f[j][k]=max(f[j-1][(k&15)<<1],f[j-1][(k&15)<<1|1])+num[j][k]; 35 ans=max(ans,f[n][i]); 36 } 37 printf("%d",ans); 38 } 39 int main() 40 { 41 init(); 42 solve(); 43 return 0; 44 }