1. 程式人生 > >[CTSC2007]動物園zoo

[CTSC2007]動物園zoo

link

試題分析

發現每個小朋友最多隻能看到$5$個動物所以考慮狀壓$dp$。我們定義$f(i,j)$為第$i$個位置從此往後$5$個人的最喜歡數量。所以只要預處理出對於每個點從後$5$個會讓多少小朋友高興即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return f*ans; } const int N=50001; const int M=50001; int n,m,cal[M][33],f[N][33]; int maxn; int main(){ n=read(),m=read(); for(int i=1;i<=m;i++){ int
s=read(),seccnt=read(),hapcnt=read(); int hap=0,sec=0; for(int j=1;j<=seccnt;j++){ int x=read();x=((x-s)%n+n)%n; sec|=(1<<(x)); } for(int j=1;j<=hapcnt;j++){ int x=read();x=((x-s)%n+n)%n; hap|=(1<<(x)); }
for(int j=0;j<32;j++) if((j&hap)||((sec&j)!=sec)) { cal[s][j]++; } } for(int i=0;i<32;i++){ memset(f,-127/3,sizeof(f)); f[0][i]=0; for(int j=1;j<=n;j++){ for(int z=0;z<32;z++) f[j][z]=max(f[j-1][(z&15)<<1],f[j-1][((z&15)<<1)|1])+cal[j][z]; } maxn=max(maxn,f[n][i]); } cout<<maxn; }
View Code