动物园 \([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 ;
}

·结尾撒花 \(\color{pink}✿✿ヽ(°▽°)ノ✿\)

动物园 (APIO 2007) 状压DP的更多相关文章

  1. 2018.09.08 bzoj1151: [CTSC2007]动物园zoo(状压dp)

    传送门 状压dp好题啊. 可以发现这道题的状压只用压缩5位. f[i][j]表示当前在第i个位置状态为j的最优值. 显然可以由f[i-1]更新过来. 因此只用预处理在第i个位置状态为j时有多少个小朋友 ...

  2. 【[APIO/CTSC2007]动物园】状压DP

    题目测评:https://www.luogu.org/problemnew/show/P3622 题目描述 新建的圆形动物园是亚太地区的骄傲.圆形动物园坐落于太平洋的一个小岛上,包含一大圈围栏,每个围 ...

  3. bzoj1231[Usaco2008 Nov]mixup2 混乱的奶牛(状压dp)

    1231: [Usaco2008 Nov]mixup2 混乱的奶牛 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1032  Solved: 588[ ...

  4. 状压dp学习笔记(紫例题集)

    P3451旅游景点 Tourist Attractions 这个代码其实不算是正规题解的(因为我蒟蒻)是在我们的hzoj上内存限制324MIB情况下过掉的,而且经过研究感觉不太能用滚动数组,所以那这个 ...

  5. 简单状压dp的思考 - 最大独立集问题和最大团问题 - 贰

    接着上文 题目链接:最大独立集问题 上次说到,一种用状压DP解决任意无向图最大团问题(MCP)的方程是: 注:此处popcountmax代表按照二进制位下1的个数作为关键字比较,即选择二进制位下1的个 ...

  6. BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]

    1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3336  Solved: 1936[Submit][ ...

  7. nefu1109 游戏争霸赛(状压dp)

    题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1109 //我们校赛的一个题,状压dp,还在的人用1表示,被淘汰 ...

  8. poj3311 TSP经典状压dp(Traveling Saleman Problem)

    题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...

  9. [NOIP2016]愤怒的小鸟 D2 T3 状压DP

    [NOIP2016]愤怒的小鸟 D2 T3 Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可 ...

  10. 【BZOJ2073】[POI2004]PRZ 状压DP

    [BZOJ2073][POI2004]PRZ Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍 ...

随机推荐

  1. 移植 uCos-III 3.03 到 STM32F429 上

    背景 通过STM32 的学习,我们可以往更深层次的地方走,尝试系统上的一些开发. STM32: F429(StdPeriph) uCos-III : v3.04 + 3.03 有关说明: 在移植 3. ...

  2. 【资料分享】全志科技T507工业核心板硬件说明书(下)

    目    录 3 电气特性 3.1 工作环境 3.2 功耗测试 3.3 热成像图 4 机械尺寸 5 底板设计注意事项 5.1 最小系统设计 5.1.1 电源设计说明 5.1.2 系统启动配置 5.1. ...

  3. vulnhub - hackme1

    vulnhub - hackme1 信息收集 端口扫描 详细扫描 目录扫描跟漏洞探测没发现什么可用信息,除了登录还有一个uploads目录应该是进入后台之后才能使用 web主页是个登录注册页面,爆了一 ...

  4. WOE编码与IV值

    参考: WOE与IV值浅谈 机器学习-变量筛选之IV值和WOE 0. Introduction WOE (weight of evidence): 证据权重 IV (information value ...

  5. 解决方案 | Windows 验证账号出现 0x80190001错误解决

    一.问题描述 点击windows开始→账户→更改账户设置→验证,出现下面的错误. 二.解决方法 网上流行的是这个方法,https://blog.csdn.net/qq_36393978/article ...

  6. 基于Java+Spring+Vue仓储出入库管理系统设计和实现

    \n文末获取源码联系 感兴趣的可以先收藏起来,大家在毕设选题,项目以及论文编写等相关问题都可以给我加好友咨询 系统介绍: 网络的广泛应用给生活带来了十分的便利.所以把仓储出入库管理与现在网络相结合,利 ...

  7. [oeasy]python020在游戏中体验数值自由_勇闯地下城_终端文字游戏

    继续运行 回忆上次内容 上次使用shell环境中的命令 命令 作用 cd 改变文件夹 pwd 显示当前文件夹 ls 列出当前文件夹下的内容 最终 进入 目录 找到 游戏   如果git clone 根 ...

  8. [oeasy]python0067_ESC键进化历史_键盘演化过程_ANSI_控制序列_转义序列_CSI

    光标位置 回忆上次内容 上次了解了 新的转义模式 \33 逃逸控制字符 esc 这个字符让输出退出标准输出流 进行控制信息的设置 可以设置光标输出的位置 ASR33中的ALT MODE 是 今天的ES ...

  9. vuex使用和场景案例

    vuex是vue提供的一个集中式状态管理器,用于对数据的集中式管理. vuex有四个重要的属性:state.mutations.actions.getters 1.vuex的使用 安装 npm ins ...

  10. 阅读翻译Mathematics for Machine Learning之2.7 Linear Mappings

    阅读翻译Mathematics for Machine Learning之2.7 Linear Mappings 关于: 首次发表日期:2024-07-23 Mathematics for Machi ...