题意:给定一个n个元素的圈,m个条件。满足一个条件需要选某些元素或不选另一些元素。

问最多能满足多少条件。每个条件所关联的元素,最远的两个距离不会超过5。

解:想了半天......

首先能想到断环成链DP。

然后某个时刻灵光一闪,突然发现可以状压最近的5个位置......这样枚举开始位置做32次DP就行了!

实现的时候发现只要枚举16种开始情况,状压4个位置...

转移就是考虑下一个位置选/不选。

注意细节......为什么有人20行A题,我写了160行呀...

 #include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm> const int N = ; struct Node {
int p, fear, like;
int a[]; // 0 none 1 fear 2 like
}node[ * N]; int f[N][], n;
std::vector<int> v[N]; inline void exmax(int &a, int b) {
a < b ? a = b : ;
return;
} inline void out(int x, int tag) {
printf(" ");
for(int i = ; i < tag; i++) {
printf("%d", (x >> i) & );
}
printf(" ");
return;
} inline int check(Node x, int s) {
for(int i = ; i < ; i++) {
if(x.a[i] == && ((s >> i) & )) {
return ;
}
if(x.a[i] == && (((s >> i) & ) == )) {
return ;
}
}
return ;
} int main() { int m;
scanf("%d%d", &n, &m);
for(int i = , x; i <= m; i++) {
scanf("%d%d%d", &node[i].p, &node[i].fear, &node[i].like);
node[i].p += ;
while(node[i].p > n) {
node[i].p -= n;
}
for(int j = ; j <= node[i].fear; j++) {
scanf("%d", &x);
for(int k = , now = node[i].p + ; k >= ; k--) {
now--;
if(!now) {
now = n;
}
if(now == x) {
node[i].a[k] = ;
break;
}
}
}
for(int j = ; j <= node[i].like; j++) {
scanf("%d", &x);
for(int k = , now = node[i].p + ; k >= ; k--) {
now--;
if(!now) {
now = n;
}
if(now == x) {
node[i].a[k] = ;
break;
}
}
}
v[node[i].p].push_back(i);
}
/// input
int ans = ;
/// -----
///
for(int op = ; op < ; op++) { /// first four
memset(f, , sizeof(f));
for(int s = ; s < ; s++) {
if(s != op) {
f[][s] = -;
}
} for(int i = ; i < n; i++) {
for(int s = ; s < ; s++) {
if(f[i][s] == -) {
continue;
}
/// f[i][s] -> f[i + 1][t] int t = s >> , temp = f[i][s]; /// put 0 don't move
for(int j = ; j < v[i + ].size(); j++) {
/// node[v[i + 1][j]] and s
temp += check(node[v[i + ][j]], s);
}
exmax(f[i + ][t], temp);
// -------------------------------------
t = t | ( << ); /// put 1 move
temp = f[i][s];
for(int j = ; j < v[i + ].size(); j++) {
temp += check(node[v[i + ][j]], s | ( << ));
}
exmax(f[i + ][t], temp);
}
}
for(int s = ; s < ; s++) {
/// f[n][s]
int temp = f[n][s], now = s << ;
for(int i = ; i < ; i++) {
now = (now >> ) + (((op >> i) & ) << );
for(int j = ; j < v[i + ].size(); j++) {
temp += check(node[v[i + ][j]], now);
}
}
exmax(ans, temp);
}
}
printf("%d\n", ans);
return ;
}

AC代码

洛谷P3622 动物园的更多相关文章

  1. 洛谷[P3622] 动物园

    状压DP 发现本题中,每个小朋友是否高兴仅取决于其后五个动物的情况,我们可以用状压DP解决本题 首先已处理 num[i][s] 表示对于位置 i ,状态为 s 时有多少在 s 的同学满意 转移方程很好 ...

  2. 洛谷 P2375 动物园

    题目详情 题目描述 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决定开设算法班,让动物们学习算法 ...

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

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

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

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

  5. 洛谷P2375 动物园

    我要死了.这是我做过的最恶心的题之一. 天下第一的大毒瘤.有gay毒. 我不如熊猫好多年... 题意:给定字符串,求g[i],表示:[0, i]中满足该子串既是前缀又是后缀还不重叠的子串数. 解:题面 ...

  6. [洛谷P2375] [NOI2014]动物园

    洛谷题目链接:[NOI2014]动物园 题目描述 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决 ...

  7. 【题解】洛谷P2375 [NOI2014] 动物园(KMP)

    洛谷P2375:https://www.luogu.org/problemnew/show/P2375 思路 这道题可以说是完全刷新了本蒟蒻对KMP的理解 感觉对next数组的理解上升到一个新的高度 ...

  8. 洛谷2375 BZOJ 3670动物园题解

    题目链接 洛谷链接 我们发现题目要我们求的num[i]东西本质上其实是 求有多少以i结尾的非前缀且能与前缀匹配的字符串,而且要求字符串长度小于(i/2) 我们先不考虑字符串长度的限制,看所有以i结尾的 ...

  9. 洛谷1640 bzoj1854游戏 匈牙利就是又短又快

    bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...

随机推荐

  1. (4)学习笔记 ) ASP.NET CORE微服务 Micro-Service ---- Consul服务发现和消费

    上一章说了  Consul服务注册  现在我要连接上Consul里面的服务 请求它们的API接口 应该怎么做呢? 1.找Consul要一台你需要的服务器 1.1 获取Consul下的所有注册的服务 u ...

  2. Unity 敌人波次设计

    一.平均时间随机敌人 将所有种类敌人预制物体放在一个列表里面,每隔时间T从列表中随机选出一个生成在场景中. 二.时间加权紧迫度随机敌人 在随机情况下每种敌人出现的概率近似相等,当敌人种类较多时,有可能 ...

  3. webpack笔记

    打包 img src src 必须以 点(.) 开始,才能被打包. 如: ./img/logo.png ../img/logo.png 使用 process a.js window.Base_Url ...

  4. Linux系统入门教程:如何在 Linux 中修改默认的 Java 版本

    提问:当我尝试在Linux中运行一个Java程序时,我遇到了一个错误.看上去像程序编译所使用的Java版本与我本地的不同.我该如何在Linux上切换默认的Java版本? 当Java程序编译时,编译环境 ...

  5. PHP从入门到精通(四)

    PHP数组中的常用函数汇总 为了更直观的讲解各函数的作用和用法,方便大家的理解,首先,我们来定义一个数组.下面各函数的操作将以本数组为例: $arr = array(1,2,3,4,5,6," ...

  6. 移动端触摸(touch)事件

    移动端时代已经到来,作为前端开发的我们没有理由也不应该坐井观天,而是勇敢地跳出心里的那口井,去拥抱蔚蓝的天空.该来的总会来,我们要做的就是接受未知的挑战.正如你所看到的,这是一篇关于移动端触摸事件的文 ...

  7. CF 1047 C. Enlarge GCD

    传送门 [http://codeforces.com/contest/1047/problem/C] 题意 给你n个数,移除最少的数字使剩下的数字GCD大于初始GCD 思路 需要一点暴力的技巧,先求出 ...

  8. STL next_permutation()

    用法 字典序全排列 可以发现函数next_permutation()是按照字典序产生排列的,并且是从数组中当前的字典序开始依次增大直至到最大字典序. 代码 #include<iostream&g ...

  9. 【2016.3.22】作业 Word count 小程序

    今天更下word count程序的设计思路及实现方法. 我的程序贴在coding里,这里就先不贴出来了, 我的coding地址:https://coding.net/u/holy_angel/p/wo ...

  10. Linux内核分析——第四章 进程调度

    第四章 进程调度 4.1 多任务 1.多任务操作系统就是能同时并发的交互执行多个进程的操作系统. 2.多任务操作系统使多个进程处于堵塞或者睡眠状态,实际不被投入执行,这些任务尽管位于内存,但是并不处于 ...