2018.08.29 NOIP模拟 movie(状压dp/随机化贪心)
【描述】
小石头喜欢看电影,选择有 N 部电影可供选择,每一部电影会在一天的不同时段播
放。他希望连续看 L 分钟的电影。因为电影院是他家开的,所以他可以在一部电影播放过程中任何时间进入或退出,当然他不希望重复看一部电影,所以每部电影他最多看一次,也不能在看一部电影的时候,换到另一个正在播放一样电影的放映厅。
请你帮助小石头让他重 0 到 L 连续不断的看电影,如果可以的话,计算出最少看几
部电影。
【输入格式】
第一行是 2 个整数 N,L,表示电影的数量,和小石头希望看的连续时间
接下来是 N 行,每行第一个整数 D(1<=D<=L)表示电影播放一次的播放时间,第二个整数是 C 表示这部电影有 C 次播放,接下来是 C 个整数表示 C 次播放的开始时间 Ti(0<=Ti<=L),Ti 是按升序给出。
【输出格式】
一个整数,表示小石头最少看的电影数量,如果不能完成输出-1
【输入样例】
4 100
50 3 15 30 55
40 2 0 65
30 2 20 90
20 1 0
【输出样例】
3
【样例说明】
开始他选择最后一步电影从 0 时间开始。
到了 20 分钟,他选择第一部电影的第一次播放,看到 65 分钟
最后他选择第二部电影的第二次播放,从 65 分钟到 100 分钟
【数据规模】
30%数据 N<=10
100%数据 N<=20, 1 <= L <= 100,000,000 ,C<=1000
唯一考场上不会正解的题。
写了个70分的随机化贪心(OJ上有90)。
先贴一发:
#include<bits/stdc++.h>
#define N 25
using namespace std;
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
int n,l,d[N],c[N],p[N],sta[N][1005];
inline int check(){
int pos=0,cnt=0;
for(int i=1;i<=n;++i){
int now=p[i];
int ppos=lower_bound(sta[now]+1,sta[now]+c[now]+1,pos)-sta[now];
if(sta[now][ppos]>pos)--ppos;
if(!ppos)return N;
if(pos>=sta[now][ppos]+d[now])++cnt;
else pos=sta[now][ppos]+d[now];
if(pos>l)return i-cnt;
}
if(pos<=l)return N;
return n-cnt;
}
int main(){
// freopen("movie.in","r",stdin);
// freopen("movie.out","w",stdout);
n=read(),l=read();
for(int i=1;i<=n;++i){
p[i]=i,d[i]=read(),c[i]=read();
for(int j=1;j<=c[i];++j)sta[i][j]=read();
}
int ans=N;
for(int i=1;i<=100000;++i)random_shuffle(p+1,p+n+1),ans=min(ans,check());
cout<<(ans==N?-1:ans);
return 0;
}
正解是状压dp,f[i]表示观看电影情况为i时能维持的最长时间,转移就从剩下的最接近的转移就行了,查找最接近右端点的值可以用lower_bound,如果想用码量与思维难度来换取时间复杂度的话可以用类似于单调队列的方法优化。
代码(lower_bound查的):
#include<bits/stdc++.h>
#define N 25
using namespace std;
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
int n,l,d[N],c[N],p[N],sta[N][1005],f[3000005],ans=21;
bool vis[3000005];
inline int lowbit(int x){return x&-x;}
inline int calc(int x){int res=0;while(x)x-=lowbit(x),++res;return res;}
inline void modify(int a,int b){vis[a]=true,f[a]=f[a]<b?b:f[a];}
int main(){
n=read(),l=read();
for(int i=1;i<=n;++i){
p[i]=i,d[i]=read(),c[i]=read();
for(int j=1;j<=c[i];++j)sta[i][j]=read();
}
vis[0]=true;
f[0]=0;
int up=1<<n;
for(int i=0;i<up;++i){
if(!vis[i])continue;
int tmp=calc(i);
if(tmp>=ans){i+=lowbit(i)-1;continue;}
if(f[i]>=l){ans=tmp;continue;}
for(int j=1;j<=n;++j){
if((i>>(j-1)&1))continue;
int pos=lower_bound(sta[j]+1,sta[j]+c[j]+1,f[i])-sta[j];
if(sta[j][pos]>f[i])--pos;
if(!pos)continue;
modify((i|(1<<(j-1))),sta[j][pos]+d[j]);
}
}
cout<<(ans==21?-1:ans);
return 0;
}
2018.08.29 NOIP模拟 movie(状压dp/随机化贪心)的更多相关文章
- NOIP模拟 乘积 - 状压dp + 分组背包
题目大意: 给出n和k,求从小于等于n的数中取出不超过k个,其乘积是无平方因子数的方案数.无平方因子数:不能被质数的平方整除. 题目分析: 10(枚举\(n\le8\)),40(简单状压\(n\le1 ...
- 2018.08.29 NOIP模拟 table(拓扑排序+建图优化)
[描述] 给出一个表格,N 行 M 列,每个格子有一个整数,有些格子是空的.现在需要你 来做出一些调整,使得每行都是非降序的.这个调整只能是整列的移动. [输入] 第一行两个正整数 N 和 M. 接下 ...
- 2018.08.29 NOIP模拟 pmatrix(线性筛)
[问题描述] 根据哥德巴赫猜想(每个不小于 6 的偶数都可以表示为两个奇素数之和),定义 哥德巴赫矩阵 A 如下:对于正整数对(i,j),若 i+j 为偶数且 i,j 均为奇素数,则 Ai,j = 1 ...
- 2018.08.18 NOIP模拟 game(数位dp)
Game 题目背景 SOURCE:NOIP2015-SHY4 题目描述 Alice 和 Bob 正在玩一个游戏,两个人从 1 轮流开始报数,如果遇到 7 的倍数或者遇到的这个数的十进制表示中含 7 , ...
- 2018.09.08 poj1185 炮兵阵地(状压dp)
传送门 状压dp经典题. 我们把每一行的状态压成01串. 预处理出每一行可能出现的状态,然后转移每个被压缩的状态的1的个数就行了. 注意当前行转移要考虑前两行的状态. 还要注意只有一行的情况. 代码: ...
- 6.28 NOI模拟赛 好题 状压dp 随机化
算是一道比较新颖的题目 尽管好像是两年前的省选模拟赛题目.. 对于20%的分数 可以进行爆搜,对于另外20%的数据 因为k很小所以考虑上状压dp. 观察最后答案是一个连通块 从而可以发现这个连通块必然 ...
- 2018.10.24 bzoj2064: 分裂(状压dp)
传送门 状压dp好题. 考虑对于两个给出的集合. 如果没有两个元素和相等的子集,那么只能全部拼起来之后再拆开,一共需要n1+n2−2n1+n2-2n1+n2−2. 如果有呢? 那么对于没有的就是子问题 ...
- 2018.08.19 NOIP模拟 dp(二分+状压dp)
Dp 题目背景 SOURCE:NOIP2015-SHY-10 题目描述 一块土地有 n 个连续的部分,用 H[1],H[2],-,H[n] 表示每个部分的最初高度.有 n 种泥土可用,他们都能覆盖连续 ...
- 2018.08.22 NOIP模拟 string(模拟)
string [描述] 给定两个字符串 s,t,其中 s 只包含小写字母以及*,t 只包含小写字母. 你可以进行任意多次操作,每次选择 s 中的一个*,将它修改为任意多个(可以是 0 个)它的前一个字 ...
随机推荐
- gulp css 压缩 合并
//导入工具包 require('node_modules里对应模块') var gulp = require('gulp'), //本地安装gulp所用到的地方 concat = require(' ...
- [ilink32 Error] Error: Unresolved external '__fastcall Data::Win::Adodb::TCustomADODataSet
[ilink32 Error] Error: Unresolved external '__fastcall Data::Win::Adodb::TCustomADODataSet::GetParam ...
- Linux tomcat启动慢, Creation of SecureRandom instance for session ID generation using [SHA1PRNG]took [xx] mil
启动慢的解决链接: http://blog.csdn.net/u011627980/article/details/54024974
- servlet的的生命周期和使用
1 Servlet的生命周期是通过Servlet接口中的init(),service(),和destroy()方法来表示的,即Servlet从创建到销毁的过程.包括如何加载和实例化,初始化,处理请求, ...
- 求数组中的逆序对的数量----剑指offer36题
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数: 如数组{7,5,6,4},逆序对总共有5对,{7,5},{7,6},{7, ...
- DOM 练习
练习一: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3 ...
- Error running : Address localhost:1099 is already in use
运行报错: Error running : Address localhost:1099 is already in use 解决方法: 打开任务管理器,将后台的java.exe进程都关掉,再次运行 ...
- poj3666(DP+离散化)
题目链接:http://poj.org/problem?id=3666 思路: 看了讨论区说本题的数据比较弱,只需要考虑不减序列即可,比较懒,所以我也只写了这一部分的代码,思路都一样,能AC就行了. ...
- linux、centos下查看系统版本、bios版本,内存信息等
1.查看系统版本 [root@localhost ~]# more /etc/issueCentOS release 6.2 (Final)Kernel \r on an \m 2.查看CPU信息 : ...
- C++中纯虚函数
1.纯虚函数 virtual ReturnType Function()= 0; 纯虚函数可以让类先具有一个操作名称,而没有操作内容,让派生类在继承时再去具体地给出定义.凡是含有纯虚函数的类叫做抽象类 ...