[CTSC2007]动物园zoo

Description
图1
图2
图3
图4

Input
输入的第一行包含两个整数 N , C,用空格分隔。 N 是围栏数(10N10000) C 是小朋友的个数(1C50000)。围栏按照顺时针的方向编号为 1,2,3,,N 。接下来的 C 行,每行描述一个小朋友的信息,以下面的形式给出: E F L X1 X2 XF Y1 Y2 YL 其中: 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 位置,i i+4 的移动情况为 S 的二进制表示;gi,S表示在第 i 位置的所有小朋友,如果i i+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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值