1. 程式人生 > >bzoj1151: [CTSC2007]動物園zoo 狀壓dp

bzoj1151: [CTSC2007]動物園zoo 狀壓dp

猴子 stream con wan 初始 cst sizeof 連續 最大

Description

新建的圓形動物園是亞太地區的驕傲。圓形動物園坐落於太平洋的一個小島上,包含一大圈圍欄,每個圍欄裏有一
種動物。如下圖所示:

你是動物園的公共主管。你要做的是,讓每個來動物園的人都盡可能高興。今天有一群小朋友來動物園參觀,你希
望能讓他們在動物園度過一段美好的時光。但這並不是一件容易的事——有的動物有一些小朋友喜歡,有的動物有
一些小朋友害怕。如,Alex 喜歡可愛的猴子和考拉,而害怕擁牙齒鋒利的獅子。而Polly 會因獅子有美麗的鬃毛
而喜歡它,但害怕有臭味的考拉。你可以選擇將一些動物從圍欄中移走以使得小朋友不會害怕。但你不能移走所有
的動物,否則小朋友們就沒有動物可看了。每個小朋友站在大圍欄圈的外面,可以看到連續的 5 個圍欄。你得到

了所有小朋友喜歡和害怕的動物信息。當下面兩處情況之一發生時,小朋友就會高興:
至少有一個他害怕的動物被移走
至少有一個他喜歡的動物沒被移走
例如,考慮下圖中的小朋友和動物:

假如你將圍欄 4 和 12 的動物移走。Alex 和 Ka-Shu 將很高興,因為至少有一個他們害怕的動物被移走了。這也
會使 Chaitanya 高興,因為他喜歡的圍欄 6 和8 中的動物都保留了。但是,Polly 和 Hwan 將不高興,因為他們
看不到任何他們喜歡的動物,而他們害怕的動物都還在。這種安排方式使得三個小朋友高興。現在,換一種方法,
如果你將圍欄 4 和 6 中的動物移走,Alex 和 Polly 將很高興,因為他們害怕的動物被移走了。Chaitanya 也會

高興,雖然他喜歡的動物 6被移走了,他仍可以看到圍欄 8 裏面他喜歡的動物。同樣的 Hwan 也會因可以看到自
己喜歡的動物 12 而高興。唯一不高興的只有 Ka-Shu。如果你只移走圍欄 13 中的動物,Ka-Shu 將高興,因為有
一個他害怕的動物被移走了,Alex, Polly, Chaitanya 和 Hwan 也會高興,因為他們都可以看到至少一個他們喜
歡的動物。所以有 5 個小朋友會高興。這種方法使得了最多的小朋友高興。

Input

輸入的第一行包含兩個整數N, C,用空格分隔。
N是圍欄數(10≤N≤10 000),C是小朋友的個數(1≤C≤50 000)。
圍欄按照順時針的方向編號為1,2,3,…,N。

接下來的C行,每行描述一個小朋友的信息,
以下面的形式給出: E F L X1 X2 … XF Y1 Y2 … YL
其中: E表示這個小朋友可以看到的第一個圍欄的編號(1≤E≤N),
換句話說,該小朋友可以看到的圍欄為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

僅輸出一個數,表示最多可以讓多少個小朋友高興

題解

看數據範圍,只有小朋友看到的欄桿範圍可以狀壓。
然後我們用\(num[i]][j]\)表示觀察範圍為\(i-(i+4)\)的小朋友在狀態為\(j\)的情況下的高興人數。
接著用\(f[i][j]\)表示觀察範圍為\(i-(i+4)\),狀態為\(j\)最多的小朋友高興人數,然後由第\(i-1\)個圍欄去不去掉轉移
\[ f[i][j]=max(f[i-1][(j\&15)<<1],f[i-1][(j\&15)<<1|1])+num[i][j] \]
又因為它是一個環,我們枚舉初始的狀態,只有結尾處的狀態與初始狀態相同的才合法,來更新答案。
然後記得每次枚舉答案時給別的狀態致負值,防止影響答案。

代碼

#include<iostream>
#include<cstdio> 
#include<cstring>
#include<algorithm> 
using namespace std;
const int maxn=1e4+10;
const int maxm=(1<<5)+10;
const int INF=0x3f3f3f3f;
int n,c,ans;
int num[maxn][maxm];
int f[maxn][maxm];
int id[maxn];
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>c;
    for(int i=1;i<=c;i++){
        int e,a,f,l,x=0,y=0,ht,lv;
        cin>>e>>f>>l;a=e;
        for(int i=1;i<=5;i++){
            if(e>n)e=1;
            id[e++]=i;
        }
        for(int i=1;i<=f;i++){
            cin>>ht;ht=id[ht];
            x|=1<<(ht-1);
        }
        for(int i=1;i<=l;i++){
            cin>>lv;lv=id[lv];
            y|=1<<(lv-1);
        }
        for(int i=0;i<(1<<5);i++)
            if((i&y)||((i^((1<<5)-1))&x))
                num[a][i]++;
    }
    for(int i=0;i<(1<<5);i++){
        memset(f[0],-INF,sizeof(f[0]));
        f[0][i]=0;
        for(int j=1;j<=n;j++) for(int k=0;k<(1<<5);k++)
            f[j][k]=max(f[j-1][(k&15)<<1],f[j-1][(k&15)<<1|1])+num[j][k];
        ans=max(f[n][i],ans);
    }
    printf("%d\n",ans);
}

bzoj1151: [CTSC2007]動物園zoo 狀壓dp