摆渡车(题目和测试右转 洛谷P5017)

做法:dp+各种优化(剪枝)

这道题考场上看了一脸懵逼...第一眼看这 tm 不是个一维dp吗...结果按着这个朦胧的思路,删删改改约莫0.5h,终于过了样例,然后一测大样例...GG了。冥思苦想了1h,最终放弃了 (感谢这白费的1.5h,迫使我T4打了个暴力,结果AC了...)

言归正传

考试完后,参考了各种题解,WA了N/A次,终于AC了这道毒瘤题,艰难的AC历程...

(〇)引子

首先来阐明一下题意:在一条数轴上有n个点,然后要求将这条数轴分为若干段(左开右闭的区间),要求:每段的两个端点之间的距离必须 >= m,求分段的最小总费用。

费用定义为:若一个点k在区间 ( j , i ] ,则这个点的费用为 i - k (可能一个位置上有多个点)

总费用定义为:所有点的费用和即为总费用

(一)如何拿分(暴力?)

讲解完题意,接下来我们要研究一个很重要的问题:如何拿分?

先看 30% 的数据:

n≤20,  m≤2,  0≤ti​≤100

看着 ti 的大小很容易想到用一维数组 f[i] 表示在第 i 分钟发车的最小费用。

然后,这TM不是个一维线性dp吗?

我们可以枚举一个 j ,即枚举前一次是在哪里发车的,这样我们便得到了状态转移方程:

这样一来,时间复杂度就是  ,30%的数据是可以过的。

(二)如何拿中分(不高也不低的分)

看一下50%的数据:

n ≤ 500,  m ≤ 100, 0 ≤ ti ≤ 10^4

nt^2的时间复杂完全过不了50%得数据,怎么办呢

通过观察(一)的状态转移方程,可以发现枚举一个k实际上是没必要的,可以用前缀和优化:

将等车人到达的时间用数组存起来,peo[ i ]表示在 0 到 i 分钟内等车人的数量,cost[ i ]表示在 0 到 i 分钟所有等车人到达时间的累积(即将 1 到 i 分钟内到达的等车人的到达时间累加起来)

就可以得到状态转移方程

分析一下时间复杂度:因为只枚举了 i 和 j ,所以时间复杂度降低为

50%的数据在 “少爷机” 上是稳稳的。

程序段:

1 for(int i=1; i<t+m; i++)
2 {
3     f[i] = i*peo[i] - cost[i];
4     for(int j=0; j<=i-m; j++)
5         f[i] = min(f[i], f[j]+(peo[i]-peo[j])*i-(cost[i]-cost[j]));
6 }

(三)如何拿高分(不是满分,考场上的高分)

自然是优化啦。问题来了,如何优化。

先看看70%的数据范围:

n≤500, m≤10, 0≤ti​≤4×10^6

很明显,t^2的时间复杂的是肯定超的。而 i 是这个状态转移方程的状态,必须要枚举,只能从 j 下手,优化这个动态规划了。

j 如何优化呢?其实,仔细想一想,很容易发现,j 没有必要从 0 枚举到 i-m,换句话说,从0到 i-m 的这段区间内,有很多状态是无用的,即这些状态一定不能构成当前 f[i] 的最优解,真正有用的只有区间 ( i-m-m+1, i-m ]。如何证明呢?

先贴一幅图:

观察上图可以发现:

当 j 在 ( R, i )中时,摆渡车回来的时间一定大于 i ,不满足状态 f[i] 的定义,舍去。

当 j 在 ( ?, L ]中时,一定可以多发一次车,使摆渡车回来的时间小于等于 i,这样得到的花费一定小于等于只发一次车的情况。因此,也可以省去。

最后,我们发现,j 只能在区间 ( L, R ] 之间才能得到最小花费,即 j 只有 m-1 种情况

于是,状态转移方程不变,j 的枚举范围改变,时间复杂度降为

70%的数据稳稳地过,甚至在 “少爷机” 上面的 score 可能 100 ( 最起码分数在70以上 )。

程序段:

1 for(int i=1; i<t+m; i++)
2 {
3     f[i] = i*peo[i] - cost[i];
4     for(int j=max(i-m-m+1,0); j<=i-m; j++)
5         f[i] = min(f[i], f[j]+(peo[i]-peo[j])*i-(cost[i]-cost[j]));
6 }

(四)70+太低了如何拿满分

老样子,再来看一下数据范围(终极boss来了):

n≤500, m≤100, 0≤ti​≤4×10^6

m的范围变回 100 了,tm的时间复杂度好方,肿么办!!!

别着急,先来分析一下数据范围:

可以发现,ti 达到了4*10^6 ,然鹅 n 却还是500,不难想象,如果将 ti 看做一条线段,上面有 4*10^6个整点,然后取其中的500个点标记,标记的点一定是非常离散的。

同样的道理,在如此之大的 ti 中,一定有很多区间是没有等车人的(无用的区间),但是仍然无用地枚举了m次,时间复杂度大大增加。

这时候,我们只需要加一个小小的剪枝,判断当前枚举的 i 点到 i-m 中是否有人,如果没有人的话,就没有必要进行多一次的循环了(因为再发多一次车对答案没有影响,毕竟没人),只需要将 f[i] 赋值为 f[i-m],然后continue即可。

经过某神犇的证明,经过这次剪枝后,实际枚举的点只有 nm 个,时间复杂度降为(当然还有一个常数 t 被我忽略了)

100%的数据跑得飞快……

程序段:

1 for(int i=1; i<t+m; i++)
2 {
3     if(i>=m and peo[i]-peo[i-m] == 0) {f[i] = f[i-m]; continue;}
4     f[i] = i*peo[i] - cost[i];
5     for(int j=0; j<=i-m; j++)
6         f[i] = min(f[i], f[j]+(peo[i]-peo[j])*i-(cost[i]-cost[j]));
7 }

(五)答案在哪?

终于到最后一步了,显而易见,answer一定在最大的时间后面(废话),只需要从 t 枚举到 t+m-1 取一个最小值即可。

注意:

代码中的 t 和 (五)中的 t 含义相同,都是最后到的那个人的到达时间。

ps:终于写完了,这个思路是参考了某神犇的(@Sooke),再加上了自己的一些理解,希望能有帮助。

转载于:https://www.cnblogs.com/GDOI2018/p/9994768.html

摆渡车(noip2018 pj t3)相关推荐

  1. NOIp2018 pj 滚粗记

    NOIp2018 pj 滚粗记 考前 一个午觉睡完就到了考场 考中 \(T1\)水题切了 \(T2\)水题切了 \(T3\)好像是\(dp\),不会,先跳 \(T4\)像树上莫队一样,然后再欧拉序上面 ...

  2. 洛谷 P5017 摆渡车

    题目传送门 解题思路: 个人感觉DP这东西,只可意会,不可言传 AC代码: 1 #include<iostream> 2 #include<cstdio> 3 #include ...

  3. POJ 327820493083

    这次的题目叫图的深度&&广度优先遍历. 然后等我做完了题发现这是DFS&&BFS爆搜专题. 3278:题目是经典的FJ,他要抓奶牛.他和牛(只有一头)在一条数轴上,他们 ...

  4. CSP-J 2020模拟赛题解

    先总结一下. 策略完全正确,对拍出了很多错误,最终一分不挂.可惜的是,第四题最后没来得及去想出正解,决定使用O(n2logn)O(n^2logn)O(n2logn)的树状数组写法,拿了606060分的 ...

  5. P5017 [NOIP2018 普及组] 摆渡车(pj组最后一道蓝) P1027 [NOIP2001 提高组] Car 的旅行路线(提高组第一道蓝)

    先从简单的说 确实 我是看着AC率高的才选的 没有辜负我的期望 他真的很简单 数据范围很小 一眼floyd 然后就秒了 注意得就是我们还是把每个点编号再跑最短路 然后我们可以把相邻的四个放一起处理 还 ...

  6. NOIP2018普及组复赛——T3摆渡车

    题目描述 有 n n n名同学要乘坐摆渡车从人大附中前往人民大学,第 i i i 位同学在第 t i t_i

  7. NOIP2018提高组省一冲奖班模测训练2 T3 XYK的音游

    10月22日NOIP2018提高组省一冲奖班模测训练2 T3 XYK的音游 题目描述 XYK最近入坑了一个新音游. 游戏界面上有Ñ个并排的按键,当前这首歌有米个鼓点.游戏的玩法是在鼓点的时刻移动鼠标到 ...

  8. P5017 NOIP2018 普及组 摆渡车

    P5017 NOIP2018 普及组 摆渡车 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 显然要把人按照到达时间排序.然后考虑 dp. 设 \(f(i)\) 表示前 \(i\) ...

  9. 【NOIP2018】摆渡车

    [题意] 1.第i个同学在第t[i]分钟到达车站 2.摆渡车一次可以装下无数人 3.两次发车的间隔时间m分钟 求所有等车时间和的最小值 [解题] 我们不妨认为时间是一条数轴,每名同学按照到达时刻分别对 ...

最新文章

  1. 使用Markdown写作
  2. Android 实现无网络传输文件(2)
  3. jQuery中Map的使用
  4. 【原创】修改C#_WinForm设计中两个默认图标
  5. 今天突然想到一个问题:地球在转动吗,由东西向西跳与由西向东跳哪个更远...
  6. python django createsuperuser创建超级管理员命令
  7. 使用NAGIOS监控网络、系统及服务
  8. python中pillow库怎么使用_Python 图像库Pillow使用
  9. java 终态类,javaoo,继承,抽象类,终态类,访问修饰符!
  10. 使用IntelliJ IDEA配置Erlang开发环境
  11. learning linux
  12. 【预测模型】基于麻雀算法改进ELMAN神经网络实现数据预测 matlab代码
  13. photoshop插件开发
  14. 数字电子技术基础知识点总结_数字电子技术课程线上授课一周之感想 ——信息与控制学院 电工基础教研室 李姿...
  15. Easy Touch参数
  16. PC端网页布局——世纪佳缘(四)注册登录
  17. 深入理解计算机系统(第二版)第四章知识整理
  18. torch.bmm()
  19. python中fp是什么意思_详解python实现FP-TREE进行关联规则挖掘(带有FP树显示功能)附源代码下载(3)...
  20. 计算机视觉——python3实现张正友棋盘相机标定图像

热门文章

  1. table 多行 宽度不一致_layui table 中固定列的行高和table行高不一致
  2. qnx 设备驱动开发_QNX驱动开发——应用层与resource manger交互 | 学步园
  3. 电子计算机职业40201,天津滨海中等专业学校
  4. ios 开发设置左滑退出_苹果铃声怎么设置自己的歌?教你用手机快速搞定!
  5. html 完全复制div中的内容_LOL手游现在远非完全体,未来还有哪些端游内容会加入手游中?...
  6. gpu编程如何一步步学习_如何学习贴片机编程
  7. 乔安监控云存储能存多长时间_干货 | 监控磁盘阵列知识介绍,不了解还不来看看?...
  8. 计算机应用基础模拟三答案,《计算机应用基础》模拟试卷三答案
  9. android搜索功能xml,Android_Android ActionBar搜索功能用法详解,本文实例讲述了Android ActionBar - phpStudy...
  10. set trans 必须是事务处理的第一个语句_MySQL中特别实用的几种SQL语句送给大家