Description

  最近一直在为了学习算法而做题,这道题是初一小神犇让我看的。感觉挺不错于是写了写。

  这道题如果是一条线的话我们可以构造一个DP f[i,j]表示以i为起点,i,i+1...i+4的取与不取的状态的二进制为j然后1~i积累的答案

  以前几乎没有这么写过,因为很难想到j是没有后效性的

  前一个状态有两种情况,i-1位取,i-1位不取

  也就是f[i-1,j >> 1] f[i-1,j >> 1+1 << 4]

  然后小朋友要怎么处理才能做到不重复不遗漏呢

  答案是记录以每个点为起点,连着5位的状态为j时从那个点出发的小朋友的开心个数

  显然当我们知道连着5位的状态时,完全可以推出该小朋友开不开心

  这一部分很容易脑补 但是真正写起来用位运算比较方便

  而i-1位是否取对当前也是没有影响的,所以这个DP就可以敲起来啦

  

  但是如何处理环形?

  固定前4位的取与不取的状态就可以啦...

  最后的时间复杂度就是DP状态的O(2^5*C)

  处理环的代价是O(2^4)

  最后是O(2^9*C) C<=5*10^5

  对于10s的时限来说还是可以过哒~

 /**************************************************************
Problem: BZOJ1151
Author: mjy0724
Time:3760 ms
Memory:30336 kb
****************************************************************/ program bzoj1151;
const maxn=;
var i,j,x,n,c:longint;
e,h,l,next,link:array[-..maxn]of longint;
hate,love:array[-..maxn,-..]of boolean;
num,f:array[-..maxn,-..]of longint; function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end; procedure solve_num;
var i,j,k,t:longint;
begin
fillchar(num,sizeof(num),);
for i:= to n do
for j:= to do
begin
k:=link[i];
while k<> do
begin
for t:= to do if (j and ( << (-t)))<> then
//这个位运算刚开始一直出错,不能写成=1因为and之后虽然只有1位是1但是不一定在最后一位QAQ
begin
if love[k,t] then
begin
inc(num[i,j]);break;//这里的break很重要 因为1个小朋友只能算一次
end;
end else
begin
if hate[k,t] then
begin
inc(num[i,j]);break;
end;
end;
k:=next[k];
end;
end;
end; procedure dp;
var head,i,j,tot,k,ans:longint;
begin
ans:=;
for head:= to do//枚举前4位的状态
begin
fillchar(f,sizeof(f),);
fillchar(f[],sizeof(f[]),);
for i:= to do
for j:=(head << i) and to (head << i) and + << i- do //and 31是小小的位运算技巧,把前面的头都去掉啦
f[i,j]:=max(f[i-,j >> ],f[i-,j >> + << ])+num[i,j]; for i:= to n- do
for j:= to do
f[i,j]:=max(f[i-,j >> ],f[i-,j >> + << ])+num[i,j];
tot:=;
for i:=n- to n do
begin
inc(tot);
for k:= to << (-tot)- do
begin
j:=k << tot+head >> (n-i);
f[i,j]:=max(f[i-,j >> ],f[i-,j >> + << ])+num[i,j];
end;
end; for i:= to do ans:=max(ans,f[n,i]);
end;
writeln(ans);
end; begin
readln(n,c);
fillchar(hate,sizeof(hate),false);
fillchar(love,sizeof(love),false);
for i:= to c do
begin
read(e[i],h[i],l[i]);
for j:= to h[i] do
begin
read(x);
if x>=e[i] then hate[i,x-e[i]+]:=true else hate[i,(x+n-e[i]) mod n+]:=true;//这里处理环的情况 表示第i个小朋友视野里的第几个是否讨厌
end;
for j:= to l[i] do
begin
read(x);
if x>=e[i] then love[i,x-e[i]+]:=true else love[i,(x+n-e[i]) mod n+]:=true;
end;
readln;
next[i]:=link[e[i]];link[e[i]]:=i;
end;
solve_num;
dp;
end.

[BZOJ1151][CTSC2007]动物园zoo 解题报告|DP|位运算的更多相关文章

  1. [bzoj1151][CTSC2007]动物园zoo_状压dp

    动物园zoo 题目大意:https://www.lydsy.com/JudgeOnline/problem.php?id=1151 题解: 我们发现每个点只会往右延伸$5$个,这个数非常小. 再加上每 ...

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

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

  3. 基于DP+位运算的RMQ算法

    来源:http://blog.csdn.net/y990041769/article/details/38405063 RMQ算法,是一个快速求区间最值的离线算法,预处理时间复杂度O(n*log(n) ...

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

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

  5. bzoj 1151: [CTSC2007]动物园zoo

    思路:因为每个人最多只能看到五个动物,我们考虑将其状压,f[ i ][ s ] 表示到了第 i 个位置, i, i + 1, i + 2, i + 3, i + 4这四个动物的状态为s, 此时的最大值 ...

  6. ACM: HDU 1028 Working out 解题报告-DP

    Working out time limit per test  2 seconds memory limit per test  256 megabytes input  standard inpu ...

  7. [CTSC2007]动物园zoo

    link 试题分析 发现每个小朋友最多只能看到$5$个动物所以考虑状压$dp$.我们定义$f(i,j)$为第$i$个位置从此往后$5$个人的最喜欢数量.所以只要预处理出对于每个点从后$5$个会让多少小 ...

  8. [jzoj 6073] 河 解题报告 (DP)

    interlinkage: https://jzoj.net/senior/#main/show/6073 description: solution: 考虑一条河$x$被染的效果 显然对于一条河$i ...

  9. [jzoj 5661] 药香沁鼻 解题报告 (DP+dfs序)

    interlinkage: https://jzoj.net/senior/#contest/show/2703/0 description: solution: 注意到这本质就是一个背包,只是选了一 ...

随机推荐

  1. DDD领域驱动设计基本理论知识总结(转)

    领域驱动设计之领域模型 为什么建立一个领域模型是重要的 领域通用语言(UBIQUITOUS LANGUAGE) 将领域模型转换为代码实现的最佳实践 领域建模时思考问题的角度 领域驱动设计的经典分层架构 ...

  2. Selenium LoadableComponent加载组件

    继承LoadableComponent类可以在打开地址时, 判断浏览器是否打开了预期的网址, 需要重写load()与isLoad()方法: 即使没有定义get()方法, 也可以进行get()方法的调用 ...

  3. 【习题集锦】全国青少年NOIP培训教材 ISBN 978-7-305-04246-1

    目录 第一章 回溯法 找路径问题 递归代码: procedure find(k:integer); {找第K步的可能性} begin if 到目的地 {表示一条路已找出} then begin 输出路 ...

  4. Linux下的命令行

    一.文件传输(两种方式) 1. 使用CRT传输 1. 一定要修改编码为UTF-8类型 1. 按住alt + p 切换成传输文件的窗口,然后拖拽文件进来即可 2. 使用类似xftp这种软件传输 这种软件 ...

  5. 常见 SQL语句使用 增删改查

    一.常见的增删改查(一).查:1.SELECT 列名称 FROM 表名称,其中列名可以是多个,中间用豆号分开,如SELECT LastName,FirstName FROM Persons: 2.SE ...

  6. LCA(最近公共祖先)——dfs+ST 在线算法

    一.前人种树 博客:浅谈LCA的在线算法ST表 二.沙场练兵 题目:POJ 1330 Nearest Common Ancestors 题解博客:http://www.cnblogs.com/Miss ...

  7. 阿里云服务器 linux下载 jdk

    直接从本地下载包上传比较慢.直接在服务器上下载安装包: 1.进入orcle官网; 2.选择需要下载的版本,下载需要同意orcle协议, 3.点击下载,获取到下载请求的cookie, 复制所有cooki ...

  8. lincode-58-四数之和

    58-四数之和 给一个包含n个数的整数数组S,在S中找到所有使得和为给定整数target的四元组(a, b, c, d). 注意事项 四元组(a, b, c, d)中,需要满足a <= b &l ...

  9. lintcode-83-落单的数 II

    83-落单的数 II 给出3*n + 1 个的数字,除其中一个数字之外其他每个数字均出现三次,找到这个数字. 样例 给出 [1,1,2,3,3,3,2,2,4,1] ,返回 4 挑战 一次遍历,常数级 ...

  10. B - 寻找M

    B - 寻找M Time Limit: 1000/1000MS (C++/Others) Memory Limit: 65536/65536KB (C++/Others) Problem Descri ...