首页 > 其他分享 >动物园 (APIO 2007) 状压DP

动物园 (APIO 2007) 状压DP

时间:2024-02-23 19:22:39浏览次数:25  
标签:移走 状压 围栏 动物 高兴 小朋友 APIO DP

动物园 \([APIO \ 2007]\)

· 题意:

新建的圆形动物园是亚太地区的骄傲。圆形动物园坐落于太平洋的一个小岛上,包含一大圈围栏,每个围栏里有一种动物。如下图所示:

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

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

每个小朋友站在大围栏圈的外面,可以看到连续的

个围栏。你得到了所有小朋友喜欢和害怕的动物信息。当下面两处情况之一发生时,小朋友就会高兴:

  • 至少有一个他害怕的动物被移走;
  • 至少有一个他喜欢的动物没被移走。

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

假如你将围栏 \(4\) 和 \(12\) 的动物移走。Alex 和 Ka-Shu 将很高兴,因为至少有一个他们害怕的动物被移走了。这也会使 Chaitanya 高兴,因为他喜欢的围栏 \(6\) 和 \(8\)中的动物都保留了。但是,Polly 和 Hwan 将不高兴,因为他们看不到任何他们喜欢的动物,而他们害怕的动物都还在。这种安排方式使得三个小朋友高兴。

现在换一种方法,如果你将围栏 \(4\) 和 \(6\) 中的动物移走,Alex 和 Polly 将很高兴,因为他们害怕的动物被移走了。Chaitanya 也会高兴,虽然他喜欢的动物 \(6\) 被移走了,他仍可以看到围栏 \(8\) 里面他喜欢的动物。同样的 Hwan 也会因可以看到自己喜欢的动物

而高兴。唯一不高兴的只有 Ka-Shu。

如果你只移走围栏 \(13\)
中的动物,Ka-Shu 将高兴,因为有一个他害怕的动物被移走了,Alex, Polly, Chaitanya 和 Hwan 也会高兴,因为他们都可以看到至少一个他们喜欢的动物。所以有 个小朋友会高兴。这种方法使得了最多的小朋友高兴。

你要求出:最多可以满足的小朋友的数量。

·数据范围

$N \leq 10^4 , C \leq 5 \times 10 ^ 4 $

·输入格式

输入的第一行包含两个整数 \(N , C\) ,用空格分隔。 \(N\) 是围栏数, \(C\) 是小朋友的个数。围栏按照顺时针的方向编号为$1,2,3\dots , N $。

接下来的 \(C\)行,每行描述一个小朋友的信息,以下面的形式给出:
\(E,F,L,X_1,\dots X_n , Y_1,\dots,Y_n\)。

其中: \(E\) 表示这个小朋友可以看到的第一个围栏的编号,换句话说,该小朋友可以看到的围栏为 \(E_1 \dots E_5\) 。注意,如果编号超过 $ n $ 将继续从 $ 1 $ 开始算。
\(F\) 表示该小朋友害怕的动物数。
\(L\) 表示该小朋友喜欢的动物数。
围栏 \(X_i\)中包含该小朋友害怕的动物。围栏 \(Y_i\)中包含该小朋友喜欢的动物。
$X_i , Y_i $ 是两两不同的整数,而且所表示的围栏都是该小朋友可以看到的。
小朋友已经按照他们可以看到的第一个围栏的编号从小到大的顺序排好了(这样最小的 \(E\) 对应的小朋友排在第一个,最大的 \(E\) 对应的小朋友排在最后一个)。

注意可能有多于一个小朋友对应的 \(E\) 是相同的。

·输出格式

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


·题解

· \(DP\)

这个题 \(GS\) 就 \(GS\) 在环上了。

如果以小朋友为基准进行 \(DP\) , 由于其并不连续,所以你并没有方法处理环。(其实这里的不可以,意思是 \(T\) )

那么就想一个能处理环还不 \(T\) 的算法。

那你的 \(DP\) 数组肯定是要开两维,那上面那种情况已经被否决了。

那么你可以这么定义这个 \(DP\) :

\(DP_{ i , j }\) : $ i $ 表示目前枚举到第 \(i\) 个栅栏, 其后面的,包括其自身的 \(5\) 个数的状态压缩一下成为 \(j\) .

那么先挂一下方程:

\[dp_{ i , j } = \max \{ dp_{ i - 1 , ( ( ( 1 << 4 ) - 1 ) \& j ) << 1 } , dp_{ i - 1 , ( ( ( 1 << 4 ) - 1 ) \& j ) << 1 | 1 } \} + b_{ i , j } \]

这个 $ b_{ i , j } $ 的意思是, 在从 \(i\) 开始 , \(j\) 为状态下, 可以让多少个小朋友高兴。存在之的充分必要条件是此点上有小朋友的观察。

那么这个 一堆的下标是表示什么的呢?

显然,$ 2 ^ 4 - 1 $ 是 \(\left(1111\right)_2\) 你拿目前的状态 \(\&\) 这个 , 相当于未保存第五位的数,即你因为 \(i\) 比 \(i-1\) 多 \(1\) 而末位多出的一位。

你现在左移一位,那么就使 \(j\) 的第四位,变成了最高位。

其实仔细的想一想,其实很有道理。你 从 $ i $ 从左往右数的第 $ 4 $ 个,不就是 $ i - 1 $ 从左往右选的第 $ 5 $ 个数。

在最低位 $ 0 $ $| \ 1 $ , 就是 $ i - 1 $ 是 $ 1 $ , 不动就是 $ 0 $ .

在原来状态得到的最大值,加上此位置小盆友的快乐数,即此状态下的最大答案。


子问题 \(1\) :如何预处理 \(b\) 数组

因为只有当 $ i $ 上有小朋友的观察时才有 \(b\) 的值 .

那么就好说了,在输入小朋友时,你用两个变量;

喜欢的,用 \(love\) 或起来;害怕的也是,用 $ fear $ 。

枚举一遍状态 $ j $ , 当:

$ j 按位与 love $ 为真 或 $ ( $ $ \ j取反 \ 按位与 \ fear )$ 为真,即可累计答案。

(这个地方好想一些,挺巧妙的)。


子问题 \(2\) : 如何处理环

考虑什么情况下可以使答案合法:

\(n\) 的状态的后四位和 \(1\) 的状态的前四位相同时。

那么如何处理得到这种情况呢?

我们可以定义一个 \(n\) 的镜像点 , 视为 \(dp_{ 0 , j }\) 。 表示第 \(n\) 个点 \(j\) 状态 。

使从此点开始 \(DP\) ,那么使其他的 \(dp_{ 0 , k } ( k \in A = \{ 1, \dots , 31 | k \ne j \} )\)
均为负无穷,此时对于后面的加减,可以抵消其作用。

最后输出 \(dp_{ n , j }\) 的最大值即可。

· \(code\)

有些东西没有用,可以恰当的删一下。

点击查看代码
#include<bits/stdc++.h>
const int C = 5e4 + 100 ; 
const int N = 1e4 + 100 ; 
const int State = ( 1 << 5 ) - 1 ; 
using namespace std ; 
int n , m ; 
class node
{
    public:
        int left , right ; 
        int num_fond , num_afraid ; 
        int fondations[ 10 ] , afraid[ 10 ] ; 
} a[ C ] ; 
int dp[ N ][ State + 1 ] ; 
int b[ N ][ State + 1 ] ; 
int papa = 0 , aiai = 0 ; 
signed main ( ) 
{
    ios::sync_with_stdio( 0 ) ; 
    cin.tie( 0 ) ; cout.tie( 0 ) ; 
    cin >> n >> m ; 
    for ( int i = 1 ; i <= m ; ++ i ) 
    { 
        cin >> a[ i ].left ; 
        papa = 0 ; aiai = 0 ; 
        cin >> a[ i ].num_afraid >> a[ i ].num_fond ; 
        for ( int j = 1 ; j <= a[ i ].num_afraid ; ++ j ) 
        {
            cin >> a[ i ].afraid[ j ] ; 
            int pp = ( a[ i ].afraid[ j ] - a[ i ].left + n ) % n ; 
            papa |= ( 1 << pp ) ; 
        } 
        for ( int j = 1 ; j <= a[ i ].num_fond ; ++ j )
        {
            cin >> a[ i ].fondations[ j ] ; 
            int pp = ( a[ i ].fondations[ j ] - a[ i ].left + n ) % n ; 
            aiai |= ( 1 << pp ) ; 
        }
        for ( int j = 0 ; j <= State ; ++ j )
        {
            if( ( j & papa ) || ( ( ~ j ) & aiai ) )
            {
                b[ a[ i ].left ][ j ] ++ ; 
            }
        }
    }
    int ans = -114514 ; 
    for ( int kala = 0 ; kala <= State ; ++ kala ) 
    {
        memset( dp[ 0 ] , 128 , sizeof ( dp[ 0 ] ) ) ; 
        dp[ 0 ][ kala ] = 0 ; 
        for ( int i = 1 ; i <= n ; ++ i )
        {
            for ( int j = 0 ; j <= State ; ++ j ) 
            {
                dp[ i ][ j ] = max ( dp[ i - 1 ][ ( ( j & ( 15 ) ) << 1 ) ] , dp[ i - 1 ][ ( ( j & ( ( 15 ) ) ) << 1 | 1 ) ] ) + b[ i ][ j ] ; 
            }
        }
        ans = max( ans , dp[ n ][ kala ] ) ; 
    }
    cout << ans ; 
}

标签:移走,状压,围栏,动物,高兴,小朋友,APIO,DP
From: https://www.cnblogs.com/hangry/p/18030240

相关文章

  • 动物园(APIO 2007)(状压DP)
    动物园题解题目描述原题来自:APIO2007新建的圆形动物园是亚太地区的骄傲。圆形动物园坐落于太平洋的一个小岛上,包含一大圈围栏,每个围栏里有一种动物。如下图所示:你是动物园的公关主管。你要做的是,让每个参观动物园的游客都尽可能高兴。今天有一群小朋友来到动物园参观,你希望......
  • 基于STM32F407MAC与DP83848实现以太网通讯三(STM32F407MAC配置以及数据收发)
    本章实现了基于STM32F407MAC的数据收发功能,通过开发板的RJ45接口连接网线到电脑,电脑使用Wiershark工具抓包验证。参考文档:DP83848IV英文DP83848EP中文STM32F4xx参考手册一、工程模板以及参考源码的获取工程源码我使用的正点原子的探索者开发板STM32F407(V2)参考源码:正点原子......
  • WiMinet 评说1.3:模拟式UDP中继技术缺陷
        在《WiMinet评说1.2:多跳无线网络的现状》一文中,我们提到:在室外长距离的无线自组织网络中,由于节点之间的链路损耗较大,其链路预算相对不足,其包误码率PER会相应升高,也就是丢包概率p会比较大;而在一个大规模网络中,某些分支节点的通讯链路又会比较深,也就是网络跳数n比......
  • 长链剖分&DP
    长链剖分优化DP长链剖分有一些美妙的性质一个点跳到根最多经过\(\sqrtn\)条链向上跳链,链长一定会增加,最坏是\(1,2,3,...,\sqrtn\)所有长链的总链长相加为n(如说)优化DP如果dp中有一维和深度有关,就考虑优化,考虑用长儿子\(O(1)\)转移(一般是平移,考虑用指针),其他暴力转......
  • 数论分块性质优化DP状态
    6311.mobitel给定一个r行s列的矩阵,每个格子里都有一个正整数。问如果从左上角走到右下角,且每次只能向右或向下走到相邻格子,那么使得路径上所有数的乘积不小于n的路径有多少条?对于100%的数据,1<=r,s<=300,1<=n<=10^6,矩阵中的数不超过10^6。so,一个普通的思想就是设f[......
  • 单调栈优化DP
    当有形如\(f_i=min_{j=0}^{l(i)}f_j+w转移代价\)我们就可以使用单调栈优化DP为什么不用单调队列???当有形如\(f_i=min_{j=l(i)}^{i-1}f_j+w转移代价\)我们就可以使用单调队列优化DP至于为毛,就可以从它的工作原理上去分析6305.最小值\(dp_i=min_{j=0}^{i-1}g_j+f(min_{x=j+1......
  • 动态DP
    动态DP最大子段和考虑设\(f_i\)表示以i为结尾的最大子段和,\(g_i\)表示i以内的最大子段和\[f_i=\max(f_{i-1}+a_i,a_i)\]\[g_i=\max(g_{i-1},f_i)\]然后非常容易将每个权值变成一个矩阵,然后每次修改就变成修改一个矩阵用线段树维护即可树上最大独立集(没有上司的舞会带修)考......
  • 基于STM32F407MAC与DP83848实现以太网通讯二(DP83848硬件配置以及寄存器)
    参考内容:DP83848数据表一、PHYDP83848功能模块图                     DP83848的硬件模块主要为:MII/RMII/SNI INTERFACES:用于与MAC数据传输的MII/RMII/SNI接口Transmit BLOCK:数据发送模块,将从外部MAC(例如STM32ETH外设的MAC)接收......
  • 基于STM32F407MAC与DP83848实现以太网通讯一(STM32以太网(ETH)外设)
    STM32F4xx可以通过以太网按照IEEE802.3-2002标准发送和接收数据。支持与外部物理层(PHY)相连的两个工业标准接口:默认情况下使用的介质独立接口(MII)(在IEEE802.3规范中定义)和简化介质独立接口(RMII)。具体的以太网(ETM)特性参考:STM32F4xx中文参考手册这里将重要的地方进......
  • 玉蟾宫(悬线dp)
    求最大子矩阵一般用采用悬线法(包好用的牢底)悬线法:[以这道题为例,我们将R称为障碍格子,将F称为非障碍格子]我们选择任意一个非障碍格子,引出三条直线:左直右直上直随后从这个点出发,分别向上左右延申直到遇到障碍格我们要求上悬线尽可能高的面积,但有可能上一......