PJ可能会用到的动态规划选讲-学习笔记

by Pleiades_Antares

难度和速度全部都是按照普及组来定的咯

数位状压啥就先不讲了

这里主要提到的都是比较简单的DP

一道思维数学巧题(补昨天)

先看一道外文题目:

(简单翻译稍微改了下,原题目戳我

现在PA要放技能,要放n(10e9)个技能,

但是放技能有冷却时间,x秒才能放一次。

PA有两个事情可以做:

  1. 有m个天赋可以学习,第i个天赋要花b[i]块钱,作用是把冷却时间改为a[i]。
  2. 可以找个打手,有k个打手可以找,请第i个打手需要花掉d[i]块钱,他会直接帮你放c[i]次技能。

m, k 10e5

给出初始金钱数,问所用的最少时间。

注意天赋最多只能学习一个,打手最多只能请一位。

拿到题目以后,我们首先要想:这道题用什么方法来做?(比如贪心,dp等等)

首先:

要枚举选择学哪个天赋 (此时我们还剩下C块钱)

然后下一步➡️找到用哪个打手比较好。



看这张图,贪心显然是不行的。

那当我们枚举完以后怎么才能选择打手呢?

——什么情况下我们绝对不会选择x这个打手

——当且仅当:有人比x便宜且比x能干活

啥时候可以贪心呢?

我们把那种又贵又不好用“名不副实”的打手给排除掉

直接对打手按照花费排序,然后如果某个打手前面有(说明比他便宜)比他能干的,那么就说明这个人名不副实。

这样排除了以后,单调的时候,➡️打手越贵就越好用

这个时候我们再选择自己能力范围内能够买到的最贵的打手就可以了哇

此时处理非常容易,二分查找就直接ok

  1. ll les(ll p)
  2. {
  3. // printf("you can use %lld to less %lld\n",(*--upper_bound(ok.begin(),ok.end(),hero(0,p))).d,(*--upper_bound(ok.begin(),ok.end(),hero(0,p))).c);
  4. return (*(--upper_bound(ok.begin(),ok.end(),hero(0,p)))).c;
  5. }

上面为二分查找orz rxz大佬写的我们这种蒟蒻就好好写正常的二分查找好了qwq

rxz大佬代码:

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <vector>
  4. #include <cstring>
  5. #include <algorithm>
  6. using namespace std;
  7. typedef long long ll;
  8. ll a[100005],b[100005];
  9. ll n,m,k,x,s;
  10. struct hero
  11. {
  12. ll c,d;
  13. friend bool operator < (hero a,hero b)
  14. {
  15. return a.d<b.d;
  16. }
  17. hero(ll _c=0,ll _d=0) {c=_c,d=_d;}
  18. };
  19. hero h[100005];
  20. vector <hero> ok;
  21. void inp()
  22. {
  23. ll i;
  24. memset(a,0,sizeof(a));
  25. memset(b,0,sizeof(b));
  26. memset(h,0,sizeof(h));
  27. ok.clear();
  28. scanf("%lld%lld%lld%lld%lld",&n,&m,&k,&x,&s);
  29. for(i=1;i<=m;i++)
  30. scanf("%lld",&a[i]);
  31. for(i=1;i<=m;i++)
  32. scanf("%lld",&b[i]);
  33. for(i=1;i<=k;i++)
  34. scanf("%lld",&h[i].c);
  35. for(i=1;i<=k;i++)
  36. scanf("%lld",&h[i].d);
  37. }
  38. void gao()
  39. {
  40. ll i,now=0;
  41. sort(h+1,h+1+k);
  42. ok.push_back(hero(0,0));
  43. for(i=1;i<=k;i++)
  44. {
  45. if(h[i].c<=now) continue;
  46. now=max(now,h[i].c);
  47. ok.push_back(h[i]);
  48. }
  49. }
  50. ll les(ll p)
  51. {
  52. // printf("you can use %lld to less %lld\n",(*--upper_bound(ok.begin(),ok.end(),hero(0,p))).d,(*--upper_bound(ok.begin(),ok.end(),hero(0,p))).c);
  53. return (*(--upper_bound(ok.begin(),ok.end(),hero(0,p)))).c;
  54. }
  55. ll calc()
  56. {
  57. ll i,t,ans=9000000000000000233;
  58. a[0]=x,b[0]=0;
  59. for(i=0;i<=m;i++) //use talent i
  60. if(s>=b[i])
  61. {
  62. if(n-les(s-b[i])>0) t=(n-les(s-b[i]))*a[i];
  63. else t=0;
  64. // printf("Use talent %lld t=%lld\n",i,t);
  65. ans=min(ans,t);
  66. }
  67. printf("%lld\n",ans);
  68. }
  69. void work()
  70. {
  71. inp();
  72. gao();
  73. calc();
  74. }
  75. int main(void)
  76. {
  77. ll t;
  78. scanf("%lld",&t);
  79. while(t--)
  80. work();
  81. return 0;
  82. }

DP选讲

DP是啥?

简单来说——哲学三连

我是谁? 【设计状态】

我从哪里来? 【从之前状态设计转移】

我到哪里去? 【向之后状态设计转移】

热身:钢条切割

钢条长度为n,可以切割。

最后,对于每个长度k,有对应价值w[k]。

问切割结束以后,所有钢条的价值和最大是多少。

辅助理解灵魂绘图:

首先,按照哲学三连来分析一下。

状态:dp[i]表示在i剁了一刀,[1,i]这段区间产生的最大价值。

从哪里来:对于所有的k,dp[i-k]都能到达dp[i]

转移方程:dp[i]=max{dp[i-k+w[k]}

一些历年的NOIP普及组题目讲解

题表见此:

P1002:过河卒

状态: dp[i][j]表示路径数

dp[i][j]可以从dp[i-1][j],dp[i][j-1]这里来

转移方程:dp[i][j]=dp[i-1][j]+dp[i][j-1]

考虑马

被马控制的点为0(不可能走到)

写一个特判:如果被控制那么就是0,否则就是刚才的那个转移方程。

过河卒属于是非常非常容易的一个dp,在考场上一定要能写出来。

P1048 采药

设计状态

dp[v]表示容量为v,装的最大价值 (有后效性)(无后效性是指:某阶段的状态一旦确定,则此后过程的演变不再受此前各状态及决策的影响)

如果一个东西有后效性,把这个东西放进dp数组的下标往往可以消除后效性。

dp[k][v] 用时为v,考虑[1,k]的药。这样就可以排除其后效性。

我是谁:

dp[k][t]考虑了前k个药,用时恰好为t,所取得的最大价值。

我从哪里来:

1⃣️k这个药没有采 dp[k-1][t]

2⃣️k这个药采了 dp[k-1][t-a[k]]+w[k] 之前用掉的时间就是t-a[k],(用a[k]的时间来采这个药)(付出了时间得到了价值)(

(3⃣️dp[k][t-1]来)

然后取一个max就做出来题目了。

单调队列

给一个数组a和一个正整数k

对于每一个长度为k的区间,求出这个区间内的最大值。







——如果一个选手比你小,还比你强,那你就打不过他了。(比如说洛谷新一代吉祥物chen_zhe先生)


题目


Dice Game

  1. // https://vjudge.net/problem/Gym-101502D
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <algorithm>
  5. using namespace std;
  6. // dp[n][k] : score=n , k is up
  7. int dp[10005][7];
  8. void move(int n,int k)
  9. {
  10. int ans,i,j;
  11. for(i=1;i<=6;i++)
  12. if(i!=k && i+k!=7)
  13. dp[n+i][i]=min(dp[n+i][i],dp[n][k]+1);
  14. }
  15. void calc()
  16. {
  17. int i,j;
  18. for(i=0;i<=10002;i++)
  19. for(j=1;j<=6;j++)
  20. dp[i][j]=23333333;
  21. dp[0][1]=0;
  22. for(i=0;i<=10002;i++)
  23. for(j=1;j<=6;j++)
  24. move(i,j);
  25. }
  26. void get()
  27. {
  28. int x,i,ans=23333333;
  29. scanf("%d",&x);
  30. for(i=1;i<=6;i++)
  31. ans=min(ans,dp[x][i]);
  32. printf("%d\n",ans==23333333?-1:ans);
  33. }
  34. int main(void)
  35. {
  36. int t;
  37. calc();
  38. scanf("%d",&t);
  39. while(t--)
  40. get();
  41. return 0;
  42. }

考前训练(复习)指南











只要你开的空间爆了不管你有没有用那么多都是一个死

PJ可能会用到的动态规划选讲-学习笔记的更多相关文章

  1. MySQL实战45讲学习笔记:第三十九讲

    一.本节概况 MySQL实战45讲学习笔记:自增主键为什么不是连续的?(第39讲) 在第 4 篇文章中,我们提到过自增主键,由于自增主键可以让主键索引尽量地保持递增顺序插入,避免了页分裂,因此索引更紧 ...

  2. 深挖计算机基础:MySQL实战45讲学习笔记

    参考极客时间专栏<MySQL实战45讲>学习笔记 一.基础篇(8讲) MySQL实战45讲学习笔记:第一讲 MySQL实战45讲学习笔记:第二讲 MySQL实战45讲学习笔记:第三讲 My ...

  3. MySQL实战45讲学习笔记:事务隔离级别(第三讲)

    一.隔离性与隔离级别 1.事务的特性 原子性 一致性 隔离性 持久性 2.不同事务隔离级别的区别 读未提交:别人改数据的事务尚未提交,我在我的事务中也能读到.读已提交:别人改数据的事务已经提交,我在我 ...

  4. MySQL实战45讲学习笔记:第二十五讲

    一.引子 在上一篇文章中,我和你介绍了 binlog 的基本内容,在一个主备关系中,每个备库接收主库的 binlog 并执行. 正常情况下,只要主库执行更新生成的所有 binlog,都可以传到备库并被 ...

  5. MySQL实战45讲学习笔记:第九讲

    一.今日内容概要 今天的正文开始前,我要特意感谢一下评论区几位留下高质量留言的同学.用户名是 @某.人 的同学,对文章的知识点做了梳理,然后提了关于事务可见性的问题,就是先启动但是后提交的事务,对数据 ...

  6. MySQL实战45讲学习笔记:第十讲

    一 .本节内容概要 前面我们介绍过索引,你已经知道了在 MySQL 中一张表其实是可以支持多个索引的.但是,你写 SQL 语句的时候,并没有主动指定使用哪个索引.也就是说,使用哪个索引是由MySQL ...

  7. MySQL实战45讲学习笔记:第十三讲

    一.引子 经常会有同学来问我,我的数据库占用空间太大,我把一个最大的表删掉了一半的数据,怎么表文件的大小还是没变? 那么今天,我就和你聊聊数据库表的空间回收,看看如何解决这个问题. 这里,我们还是针对 ...

  8. 动态规划 Dynamic Programming 学习笔记

    文章以 CC-BY-SA 方式共享,此说明高于本站内其他说明. 本文尚未完工,但内容足够丰富,故提前发布. 内容包含大量 \(\LaTeX\) 公式,渲染可能需要一些时间,请耐心等待渲染(约 5s). ...

  9. MySQL实战45讲学习笔记:日志系统(第二讲)

    一.重要的日志模块:redo log 1.通过酒店掌柜记账思路刨析redo log工作原理 2.InnoDB 的 redo log 是固定大小的 只要赊账记录在了粉板上或写了账本上,之后即使掌柜忘记了 ...

随机推荐

  1. AcceptEx与完成端口(IOCP)结合实例

    前言 在windows平台下实现高性能网络服务器,iocp(完成端口)是唯一选择.编写网络服务器面临的问题有:1 快速接收客户端的连接.2 快速收发数据.3 快速处理数据.本文主要解决第一个问题. A ...

  2. 函数调用的区别:_cdecl以及_stdcall

    一.概念1)_stdcall调用   _stdcall是Pascal程序的缺省调用方式,参数采用从右到左的压栈方式,由调用者完成压栈操作,被调函数自身在返回前清空堆栈.   WIN32 Api都采用_ ...

  3. 深度学习论文翻译解析(三):Detecting Text in Natural Image with Connectionist Text Proposal Network

    论文标题:Detecting Text in Natural Image with Connectionist Text Proposal Network 论文作者:Zhi Tian , Weilin ...

  4. MySQL 解压缩版安装 2017-12-02(完整版,包括异常处理)

    一.安装 1.到mysql官网 http://dev.mysql.com/downloads/mysql/ 下载mysql 注:msi的是安装版     zip是压缩版 2.解压 解压到想安装的目录下 ...

  5. JavaWeb学习 (七)————HttpServletResponse对象(一)

    一.HttpServletResponse对象介绍

  6. XtraBackup的备份原理与应用示例

    一.XtraBackup简介与安装 XtraBackup是一款免费的在线开源数据库备份解决方案,适用于所有版本的MySQL和MariaDB.XtraBackup支持对InnoDB热备,是一款物理备份工 ...

  7. C++ 日期 & 时间

    C++ 标准库没有提供所谓的日期类型.C++ 继承了 C 语言用于日期和时间操作的结构和函数. 为了使用日期和时间相关的函数和结构,需要在 C++ 程序中引用 头文件. 有四个与时间相关的类型:clo ...

  8. Java中的集合迭代器

    集合的迭代器 任何集合都有迭代器. 任何集合类,都必须能以某种方式存取元素,否则这个集合容器就没有任何意义. 迭代器,也是一种模式(也叫迭代器模式).在java中它是一个对象,其目的是遍历并选中其中的 ...

  9. Java 面向对象编程小练习(曾经)

    最近打算将之前学习过的小练习分享出来,算是巩固知识.虽然是小练习,但是越看越觉得有趣,温故而知新. 练习:功能跳水比赛,8个评委评分.运动员成绩去掉最高和最低之后的平均分 代码实例: 1.导包 imp ...

  10. idea/ecipse中使用maven集成springmvc相关jar包时候,出错:java.lang.ClassNotFoundException: org.springframework.web.servlet.DispatcherServlet

    参考stackoverflow:https://stackoverflow.com/questions/11227395/java-lang-classnotfoundexception-org-sp ...