[APIO2007]动物园

状压DP

先预处理出来pre[i][S]表示对于第i个位置,往后5个的状态是S时,开心的小朋友的数量。

然后dp的时先枚举前5个的状态,再dp。

因为围栏是环状的,之后统计答案时统计的是那个f[n][S]=startS的。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n,m,hsta,lsta,pre[10005][33],f[10005][33],cnt;
void Dfs(int E,int dep,int sta) {
    if(dep==5) {
        if(sta&lsta||(sta&hsta)!=hsta) pre[E][sta]++;
        return;
    }
    Dfs(E,dep+1,sta|(1<<dep));
    Dfs(E,dep+1,sta);
}
int main() {
    scanf("%d%d",&m,&n);
    for(int i=1,e,h,l,x;i<=n;i++) {
        scanf("%d%d%d",&e,&h,&l);
        hsta=lsta=0;
        while(h--) scanf("%d",&x),x=(x-e+m)%m,hsta|=(1<<x);
        while(l--) scanf("%d",&x),x=(x-e+m)%m,lsta|=(1<<x);
        Dfs(e,0,0);
    }
    int ans=0;
    for(int S=0;S<32;S++) {
        memset(f[0],0xcf,sizeof f[0]);
        f[0][S]=0;
        for(int i=1;i<=m;i++)
            for(int j=0;j<32;j++)
                f[i][j]=max(f[i-1][(j&15)<<1],f[i-1][(j&15)<<1|1])+pre[i][j];
        ans=max(ans,f[m][S]);
    }
    cout<<ans<<endl;
    return 0;
}
动物园

 

posted @ 2018-10-11 16:18  SWHsz  阅读(229)  评论(0编辑  收藏  举报