[CTSC2007]动物园zoo

来源:互联网 发布:秦安观点 网络强国 编辑:程序博客网 时间:2024/04/29 12:13

Description
图1
图2
图3
图4

Input
输入的第一行包含两个整数N, C,用空格分隔。N是围栏数(10N10000)C是小朋友的个数(1C50000)。围栏按照顺时针的方向编号为1,2,3,,N。接下来的C行,每行描述一个小朋友的信息,以下面的形式给出: E F L X1 X2XF Y1 Y2YL 其中: E表示这个小朋友可以看到的第一个围栏的编号(1EN),换句话说,该小朋友可以看到的围栏为E,E+1,E+2,E+3,E+4。注意,如果编号超过N将继续从1开始算。如:当N=14,E=13时,这个小朋友可以看到的围栏为13,14,1,2和3。F表示该小朋友害怕的动物数。L表示该小朋友喜欢的动物数。围栏X1,X2,,XF 中包含该小朋友害怕的动物。围栏Y1,Y2,,YL 中包含该小朋友喜欢的动物。 X1,X2,,XF,Y1,Y2,,YL是两两不同的整数,而且所表示的围栏都是该小朋友可以看到的。小朋友已经按照他们可以看到的第一个围栏的编号从小到大的顺序排好了(这样最小的E对应的小朋友排在第一个,最大的E对应的小朋友排在最后一个)。注意可能有多于一个小朋友对应的E是相同的。

Output
仅输出一个数,表示最多可以让多少个小朋友高兴。

样例输入1
14 5 5
2 1 2 4 2 6
3 1 1 6 4
6 1 2 9 6 8
8 1 1 9 12
12 3 0 12 13 2

样例输入2
12 7 6
1 1 1 1 5
5 1 1 5 7
5 0 3 5 7 9
7 1 1 7 9
9 1 1 9 11
9 3 0 9 11 1

样例输出1
5

样例输出2
6

HINT

Source

思路
fi,S表示在第i位置,ii+4的移动情况为S的二进制表示;gi,S表示在第i位置的所有小朋友,如果ii+4的移动情况为S的二进制表示,那么会使多少人高兴。那么fi可以由fi1通过去掉第i1位再加上i+4的状态转移过来。

代码

#include <cstdio>#include <algorithm>#include <cstring>const int maxn=10000;int f[maxn+10][32],g[maxn+10][32];int n,m,ans;int main(){    scanf("%d%d",&n,&m);    for(int i=1; i<=m; i++)    {        int w,l,h,lv=0,hv=0;        scanf("%d%d%d",&w,&l,&h);        for(int j=1; j<=l; j++)        {            int k;            scanf("%d",&k);            k=(k+n-w)%n;            lv|=1<<k;        }        for(int j=1; j<=h; j++)        {            int k;            scanf("%d",&k);            k=(k+n-w)%n;            hv|=1<<k;        }        for(int j=0; j<32; j++)        {            if((lv&j)||(hv&(31^j)))            {                g[w][j]++;            }        }    }    for(int s=0; s<16; s++)    {        memset(f[0],200,sizeof f[0]);        f[0][s<<1]=0;        for(int i=1; i<=n; i++)        {            for(int j=0; j<32; j++)            {                f[i][j]=std::max(f[i-1][(j&15)<<1],f[i-1][(j&15)<<1|1])+g[i][j];            }        }        ans=std::max(ans,std::max(f[n][s<<1],f[n][s<<1|1]));    }    printf("%d\n",ans);    return 0;}
原创粉丝点击