题目链接

比较费脑子的一道题

先说题目核心思想 : 状压dp

环的处理我们先不管。

我们设 dp[j][s] 表示 到达动物 j 且 [ j , j+5) 这五个动物状态为s时 最多能使多少小朋友开心。

其中,s为 0~31 的整数,二进制下的s表示[ j , j+5) 这五个动物状态,0表示不选,1表示选,特别注意,[ j , j+5) 分别对应s从右往左数的每个数字,例如s = 18 ,二进制下表示为10010 ,即 j 到 j+4 的状态为 0 , 1 , 0 , 0 , 1。

可得状态转移方程:dp[j][s] = min( dp[j-1][(s&15)<<1] , dp[j-1][(s&15)<<1|1] ) + num[j][s];

解释:15 的二进制为01111,(s&15) 即取 [ j , j+5) 的前 4 个数的状态。然后 <<1 代表作为 [j-1 , j+4)的后四个状态,对j-1的状态枚举一下是0还是1,取个min,再加上num[j][s]就行了

num[j][s]为已经预处理出来的数组,它的意思为:

状态为s时,某几个视野为[j , j+5)的小朋友中高兴地人数

还是有点懵?没事,将上面的解释结合下图来看:

当前 j=3 , s=18 (10010) , s&5=2 (0010)
动物: 1 2 3 4 5 6 7 8 9 10
下标: j-1 j j+1 j+2 j+3 j+4
s状态: 0 1 0 0 1
(s&5)为: 0 1 0 0
(s&5)>>1状态: 0 0 1 0 0
(s&5)>>1|1状态: 1 0 1 0 0

这样就比较好理解了。

num的预处理

可随读入一起处理:

for(int i=;i<=m;i++){
int E=read(),F=read(),L=read(),fear=,like=;
for(int j=;j<=F;j++){
int x=read() ;
x=(x-E+n)%n;
fear|=(<<x);//fear表示这五个围栏中这个小朋友害怕的动物的状态
}
for(int j=;j<=L;j++){
int x=read();
x=(x-E+n)%n;
like|=(<<x);//like表示这五个围栏中这个小朋友喜欢的动物的状态
}
for(int j=;j<;j++)//0-> 拿走 1->留下
if((fear&~j)||(like&j))
num[E][j]++;
}

较难理解的几点:1.x = (x-E+n)%n,fear |= (1<<x)

这个为环的处理,手推几个式子就能得出

2.(fear&~j)||(like&j)

看题目条件:

  • 至少有一个他害怕的动物被移走

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

这里留给读者自行思考,不再解释( '~'符号为取反,即0变1,1变0

然后就是最后dp环的处理:

可以枚举开始的状态 ,设开始0的状态为 i 则最后的状态只有 dp[n][i] 对答案有效,强制和开始的状态一样

OK结束,代码:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
int n,m,ans;
int num[][];
int dp[][];
inline int read(){
int x=;
char ch=getchar();
while(ch<''||ch>'')
ch=getchar();
while(ch>=''&&ch<=''){
x=(x<<)+(x<<)+(ch^);
ch=getchar();
}
return x;
}
int main(){
n=read(),m=read();
for(int i=;i<=m;i++){
int E=read(),F=read(),L=read(),fear=,like=;
for(int j=;j<=F;j++){
int x=read() ;
x=(x-E+n)%n;
fear|=(<<x);
}
for(int j=;j<=L;j++){
int x=read();
x=(x-E+n)%n;
like|=(<<x);
}
for(int j=;j<;j++)//0-> 拿走 1->留下
if((fear&~j)||(like&j))
num[E][j]++;
}
for(int i=;i<=n;i++){
for(int j=;j<;j++){
cout<<num[i][j]<<" ";
}
cout<<endl;
}
for(int i=;i<;i++){
memset(dp[],,sizeof(dp[]));
dp[][i]=;
for(int j=;j<=n;j++)
for(int s=;s<;s++)
dp[j][s]=max(dp[j-][(s&)<<],dp[j-][(s&)<<|])+num[j][s];
if(ans<dp[n][i])//开始状态为 i 结尾状态也得是i才能更新ans
ans=dp[n][i];
}
cout<<ans;
return ;
}

Luogu [P3622] [APIO2007]动物园的更多相关文章

  1. P3622 [APIO2007]动物园

    题目链接 题意分析 这是一道状压\(DP\)的题 一个人只可以欣赏到\(5\)只动物 显然可以状压 我们用\(dp[i][j]\)表示当前\([i,i+4]\)中这\(5\)只动物的状态\(j\) 在 ...

  2. 洛谷 P3622 [APIO2007]动物园【状压dp】

    看成网络流建图想了好久... 实际上5个是可以状压的 设f[i][k]为到第i个围栏状态为k的方案数,因为考虑到重复,设g[i][k]记录i开始,状态为k的孩子有几个 状态转移很好想:f[j][k]= ...

  3. P3622 [APIO2007]【一本通提高状态压缩类动态规划】动物园

    广告 绿树公司 - 官方网站:https://wangping-lvshu.github.io/LvshuNew/ 绿树智能 - 官方网站:https://wangping-lvshu.github. ...

  4. [APIO2007]动物园 --- 状压DP

    [APIO2007]动物园 题目描述 新建的圆形动物园是亚太地区的骄傲.圆形动物园坐落于太平洋的一个小岛上,包含一大圈围栏,每个围栏里有一种动物. 如下图所示: 你是动物园的公共主管.你要做的是,让每 ...

  5. 题解 洛谷P3622/BZOJ1151【[APIO2007]动物园】

    这一道题,我也是搞了很久才搞懂的(也就两个多小时). 感谢Rayment大佬的题解! 我们进入正题. 对于一个笼子里的动物,我们可以选择撤走或不撤走,可以用0和1来表示,很容易就想到二进制,想到状压d ...

  6. [APIO2007]动物园

    题目描述 新建的圆形动物园是亚太地区的骄傲.圆形动物园坐落于太平洋的一个小岛上,包含一大圈围栏,每个围栏里有一种动物. 你是动物园的公共主管.你要做的是,让每个来动物园的人都尽可能高兴.今天有一群小朋 ...

  7. 【[APIO2007]动物园】

    我好\(sb\)啊,把\(>>\)打成\(<<\)结果就写了两节课 那个一个人只能看到五个动物显然很鬼畜 那我们就可以压这一维了 \(dp[i][s]\)表示从第\(i\)个位 ...

  8. 【题解】APIO2007动物园

    首先一眼感受到这题特别的性质……5个?这么小的,感觉就像是状压.脑补了一下,如果没有环的话应该很好做吧……有环怎么办?5真的很小的,随便乱搞肯定也可以.那就放在外面暴力枚举吧.然后正解就出来了. 然而 ...

  9. Luogu 2375 [NOI2014]动物园

    字胡串什么的一直不太会,感觉这题…还蛮本质的 考虑暴力求解:num[i]相当于从一直跳nxt,如果nxt[j] * 2 <= i 那么就累加答案 其实这是一个树的结构,也就是说跳到一个结点满足条 ...

随机推荐

  1. java多线程:继承Thread和实现Runable接口的区别

    java中我们想要实现多线程常用的有两种方法,继承Thread 类和实现Runnable 接口,有经验的程序员都会选择实现Runnable接口 ,其主要原因有以下两点: 首先,java只能单继承,因此 ...

  2. (八)装配Bean(2)

    二.在Java类中进行显式的装配 显式配置有两种: 1. 一种是在java(本文讲解)   2. 另一种是xml配置文件(第一章有讲) 案例一: 使用java显式装配+@autowired自动装配的方 ...

  3. (三)springmvc之注解的基本使用

    一.@Controller @Controller 标记一个类是Controller 二.RequestMapping  地址映射 2.1 Value的操作. 注解在类上面    (父)       ...

  4. SpringMVC 出现 406(Not Acceptable)

    首先,需要清楚,http state 406代表什么意思: 406是HTTP协议状态码的一种,表示无法使用请求的特性来响应请求的网页.一般指客户端浏览器不接受所请求页面的MIME类型. 出现这样的错误 ...

  5. springboot中使用验证码kaptcha

    1.pom.xml引入kaptcha所需要的jar包 <!-- 验证码 --> <dependency> <groupId>com.github.penggle&l ...

  6. 奇妙的算法【10】TX--有效号码、最,小耗时、最小差值、差值输出、异或结果

    昨晚刚刚写的几道算法题,难度也还行,就是全部AC有些困难,当时第一题AC.第二题AC 60%,第四题AC 40%,第五题没有时间写完了,这个应该全部AC了:其中第三题没有写出来 1,是否存在符合规范的 ...

  7. c# winfrom 子窗体分屏显示

    参考博客:https://blog.csdn.net/kailan818/article/details/8517126 实现代码: private void button1_Click(object ...

  8. A*算法与8数字谜题(参见《算法》P226习题2.5.32)

    A*算法的目的是找到一条从起始状态到最终状态的最短路径. 在A*算法中,需要在每个点计算启发函数:f(S) = g(S) + h(S),其中g(S)是从起点到S点的距离,h(S)是对从S点到终点的最短 ...

  9. 注解@Slf4j使用

    我们在写代码的时候需要加入日志打印,如果不想每次都写private  final Logger logger = LoggerFactory.getLogger(XXX.class); 那么可以用注解 ...

  10. css border-raidus 百分比和数值设置效果不同

    1.水平方向和竖直方向半径相等:设置数值和百分比的效果是一样的: 2.水平方向和竖直方向半径不相同:则效果不一致,具体参见:http://www.zhangxinxu.com/wordpress/20 ...