【状态压缩DP】[APIO2007]动物园

2040: 【APIO2007】动物园
时间限制: 1 Sec 内存限制: 128 MB
提交: 22 解决: 8
[提交][状态][我的提交]
题目描述
新建的圆形动物园是亚太地区的骄傲。圆形动物园坐落于太平洋的一个小岛上,它包含一大圈围栏,每个围栏里有一种富有异国风情的动物。如下图所示:

这里写图片描述
你是动物园的公关主管。你要做的是,让每个参观动物园的游客都尽可能高
兴。今天有一群小朋友来到动物园参观,你希望能让他们在动物园度过一段美好
的时光。但这并不是一件容易的事——有些小朋友喜欢某些动物,而有些小朋友
则害怕某些动物。例如,Alex 喜欢可爱的猴子和考拉,而害怕拥有锋利牙齿的
狮子。而 Polly 会因狮子有美丽的鬃毛而喜欢它,但害怕有臭味的考拉。

你可以选择将一些动物从围栏中移走以使得小朋友不会害怕。但你移走的动
物也不能太多,否则留给小朋友们观赏的动物就所剩无几了。

每个小朋友站在大围栏圈的外面,可以看到连续的 5 个围栏。你得到了所有
小朋友喜欢和害怕的动物信息。当出现下面两种情形之一时,小朋友就会高兴:
(1)至少有一个他害怕的动物(从视线可见的范围内)被移走,或
(2)至少有一个他喜欢的动物没有被(从视线可见的范围内)移走。

例如,考虑下图中的小朋友和动物:

这里写图片描述

这里写图片描述

假如你将围栏 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 个小朋友会高兴。这种方法使得最多的小朋友高兴。

输入
输入的第一行包含两个整数 N, C,用空格分隔。N 是围栏数(10≤N≤10 000),
C 是小朋友的个数(1≤C≤50 000)。围栏按照顺时针的方向编号为 1,2,3,…,N。
接下来的 C 行,每行描述一个小朋友的信息,以下面的形式给出:

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

样例输入
Copy (如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)

14 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
样例输出
5
提示
来源

[提交][状态][讨论版]

分析:
f[i][j]:i表示起始点,j表示动物的取舍状态。
num[i][j]表示以i开始j这种状态最多能令多少个站在j这个位置的小朋友满意。

f[i][j]=max(f[i][(j<<1)&31],f[i][(j<<1)&31+1]+num[i][j];

因为是环形,所以前4个应该固定,枚举前4个的取舍状态。

#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXC 10000
#define MAXE 5
void Read(int &x){
    char c;
    while(c=getchar(),c!=EOF)
        if(c>='0'&&c<='9'){
            x=c-'0';
            while(c=getchar(),c>='0'&&c<='9')
                x=x*10+c-'0';
            ungetc(c,stdin);
            return;
        }
}
int n,c,x,y,e,f[MAXC+10][1<<MAXE],num[MAXC+10][1<<MAXE],ans;
void dfs(int pos,int dep,int status)
{
    if (dep>4)
    {
        if((y&status)||(x&status)!=x)
            num[e][status]++;
        return;
    }
    dfs(pos,dep+1,status);
    dfs(pos,dep+1,status|(1<<dep));
}
void dp(int st){
    int q,i,j,w1,w2,r;
    for(j=0;j<32;j++)
        f[0][j]=0;
    for(i=1;i<=n;i++)
        if(i<5)
            for(j=0;j<32;j++){
                q=st>>(i-1);
                r=(1<<(5-i))-1;
                if((j&r)==q){
                    w1=(j<<1)&31,w2=w1+1;
                    f[i][j]=max(f[i-1][w1],f[i-1][w2])+num[i][j];
                }
                else
                    f[i][j]=0;
            }
        else if(i+4<=n)
            for(j=0;j<32;j++){
                w1=(j<<1)&31,w2=w1+1;
                f[i][j]=max(f[i-1][w1],f[i-1][w2])+num[i][j];
            }
        else{
            q=st&((1<<(i+4-n))-1);
            for(j=0;j<32;j++)
                if(j>>(n+1-i)==q){
                    w1=j<<1&31,w2=w1+1;
                    f[i][j]=max(f[i-1][w1],f[i-1][w2])+num[i][j];
                }
                else
                    f[i][j]=0;
        }
    for(j=0;j<32;j++)
        ans=max(f[n][j],ans);
}
int main()
{
    int i,j,t,cx,cy;
    Read(n),Read(c);
    for(i=1;i<=c;i++){
        x=y=0;
        Read(e),Read(cx),Read(cy);
        for(j=1;j<=cx;j++)
            Read(t),x|=1<<((t+n-e)%n);
        for(j=1;j<=cy;j++)
            Read(t),y|=1<<((t+n-e)%n);
        dfs(i,0,0);
    }
    for(i=0;i<16;i++)
        dp(i);
    printf("%d",ans);
}
posted @ 2015-09-28 15:12  outer_form  阅读(234)  评论(0编辑  收藏  举报