习题课3-1

数字三角形

  • 一个三角形(金字塔状)有n行,第i行有i个数字,数字错位排列

  • 求出从顶端走到底端的一条路径,满足路径上的数字之和最大,同时在路径上行走时,每次只能走到下一行相邻的数字上

  • 4
    1
    2 3
    4 5 6
    7 8 9 10
    
  • 输出20

  • 每一次都要向下走一行,同时只能走到相邻两个点上,不会走回头路

  • 每行只会经过一个点

  • 在三角形某个位置(i,j)上,可以发现只有两个点可以走进该点,即(i-1,j),(i-1,j-1)

解法1

  • 写一个搜索,从顶端向下找出所有到达底端的路径

  • 会有大量重复

解法2

  • a(i,j)表示位置(i,j)上的数字,d(i,j)能得到的最优路径之和

  • 某一个点的d(i,j),只能是d(i-1,j)和d(i-1,j-1)走过来,找出其大者,同时加上当前点a(i,j),即可写出状态转移方程

  • d(i,j)=max{d(i−1,j−1),d(i−1,j)}+a(i,j)d(i,j) = max\{d(i-1,j-1),d(i-1,j)\} +a(i,j) d(i,j)=max{d(i−1,j−1),d(i−1,j)}+a(i,j)

  • i-1 j-1有可能越界,在外面包一层0,取max的时候自动就会取里面的数字非0的数字

  • 最后答案就是:

  • max{d(n,j)∣1≤i≤n}max\{d(n,j)|1\leq i\leq n\} max{d(n,j)∣1≤i≤n}

  • 即,动态规划

  • 不会走到重复的地方->无后效性->有向无环图

  • 每次只有两个决策->选一个最优的决策->全局最优

  • 最后在底端一行里面比较出最大者

  • 时间复杂度,每一次取了3次常数O(3) = O(1),状态树一共有n的平方个状态,所以就是O(n2)

背包问题1

  • n种物品,每种物品有相应的价值和体积,物品分为两类,一类是单个物品,即该物品只有一个,一类是多个物品,即该物品有无限个
  • 给定一个体积为V的背包,求一种装填方案使得价值之和最大

问题分析

  • 单个物品用经典01背包
  • 无限物品,即完全背包

解法1

01背包

  • 令f(i,j)表示前i个物品,用一个容量为j的背包能装下物品(不能超过容量j,最大等于j)的最大价值之和

  • 体积为v,价值为w的物品i,然后对于容量为j的背包

  • f(i,j)=max{f(i−1,j),f(i−1,j−v)+w}f(i,j) = max \{f(i-1,j),f(i-1,j-v)+w\} f(i,j)=max{f(i−1,j),f(i−1,j−v)+w}

  • 对于某个物品,两个策略就是放与不放

  • 不放就是f(i-1,j),放的话就是f(i-1,j-v)+w

完全背包

  • 类似于01背包

  • f(i,j)=max{f(i−1,j),f(i,j−v)+w}f(i,j) = max \{f(i-1,j),f(i,j-v)+w\} f(i,j)=max{f(i−1,j),f(i,j−v)+w}

  • f(i,j-v):前i个物品,容量为j-v的背包,也就是说我们可能已经在这个j-v的背包里放过一些物品i了,这就包含了无限物品的意思。

  • 更详细的解释:将无限个物品拆成一个一个的,然后做01背包,假如第a个物品到第b个物品都是我们拆的物品(完全相同的而且足够多),那么根据01背包,我们有:

  • KaTeX parse error: Undefined control sequence: \ at position 54: …},a\leq i\leq b\̲ ̲

  • 我们将f(a…)、f(a+1…)、…、f(b,…)这些数组取最大值和到一起

滚动数组

  • 01背包更新时只用到了<i的值,所以可以重复利用信息

  • 01背包可以这些写(倒序枚举j)

  • f(i,j)=max{f(j),f(j−v)+w}f(i,j) = max \{f(j),f(j-v)+w\} f(i,j)=max{f(j),f(j−v)+w}

  • 倒序枚举计算时,在枚举物品i时,在倒序计算时,体积j时从后往前更新最大价值,此时后面的值等于前面的值加上物品i的价值,而前面的最大价值没有考虑加入物品i的情况,所以只考虑加入一次的情况

  • 完全背包可以这样写(顺序枚举j)

  • f(i,j)=max{f(j),f(j−v)+w}f(i,j) = max \{f(j),f(j-v)+w\} f(i,j)=max{f(j),f(j−v)+w}

  • 顺序枚举时,在枚举物品i是,背包体积是从前往后更新最大价值,此时后面的值更新时,前面的最大价值计算已经考虑了加入1,2,…,若干件i的情况,此时就考虑了这个背包装满时最大能装物品i的情况,也就是无穷物品

  • 得到的结果和二维结果一样

public class beibaowenti1_3_1 {public static void main(String[] args) {InputStream inputStream = System.in;OutputStream outputStream = System.out;InputReader in = new InputReader(inputStream);PrintWriter out = new PrintWriter(outputStream);Task solver = new Task();solver.solve(in, out);out.close();}static class Task {// ================= 代码实现开始 =================/* 请在这里定义你需要的全局变量 */final int N = 5005;int[] f = new int [N];// n:物品个数// V:背包的体积// t:长度为n的数组,第i个元素若为0,表示物品i为单个物品;若为1,表示物品i为多个物品。(i下标从0开始,下面同理)// w:长度为n的数组,第i个元素表示第i个物品的价值// v:长度为n的数组,第i个元素表示第i个物品的体积// 返回值:最大价值之和int getAnswer(int n, int V, List<Integer> t, List<Integer> w, List<Integer> v) {/* 请在这里设计你的算法 */for (int i = 0; i < n; i++) {if (t.get(i) == 0) {// 01背包// 倒序计算不具备累加性,每种物品只算了一次// f[5] = max(f[5],f[5-v(0)]+w(0))对于体积为5的背包,只算了装一次序号0物品的情况for (int j = V; j >=v.get(i) ; j--) {f[j] = Math.max(f[j],f[j-v.get(i)]+w.get(i));}}else {// 完全背包// 正序计算具备累加性,物品可以算任意次,只要不超过背包体积// f[v(0)] = max(f[v(0)],f[v(0)-v(0)]+w(0))// f[v(0)+v(0)] = max(f[v(0)+v(0)],f[v(0)]+w(0))for (int j = v.get(i); j <=V ; j++) {f[j] = Math.max(f[j],f[j-v.get(i)]+w.get(i));}}}return f[V];}// ================= 代码实现结束 =================void solve(InputReader in, PrintWriter out) {int n = in.nextInt(), V = in.nextInt();List<Integer> T = new ArrayList<>();List<Integer> W = new ArrayList<>();List<Integer> _V = new ArrayList<>();for (int i = 0; i < n; ++i) {int t = in.nextInt(), w = in.nextInt(), v = in.nextInt();T.add(t);W.add(w);_V.add(v);}out.println(getAnswer(n, V, T, W, _V));}}

拓展

  • 01背包,选与不选
  • 完全背包,每个物品有无限个,想选多少选多少
  • 多重背包,物品不是有限个,但是有多个,同样是想选多少选多少

背包问题2

  • n个物品,每个物品有一个体积和价值
  • q次询问,若把物品x丢弃,剩下的物品装进大小为V的背包得到的最大价值是多少?

问题分析

  • 把剩下的物品直接拿来做01背包,可以通过一部分数据

  • 把容量为V的背包,拆分成两个背包,体积分别是V1、V2(V1+V2=V)

  • 假若我们将一堆物品分成了两份,然后分别将每一份撞到拆出来的背包里,同时求出最优解,那么

  • Ans(V)=max{Ans1(V1)+Ans2(V2)∣V1+V2=V,V1,V2>=0}Ans(V) = max\{Ans1(V1)+Ans2(V2)|V1+V2=V,V1,V2>=0\} Ans(V)=max{Ans1(V1)+Ans2(V2)∣V1+V2=V,V1,V2>=0}

  • 对应到题目,如果丢弃的是x,x序号之前的物品用v1背包装,x序号之后的物品用v2背包装

public class beibaowenti2_3_1 {public static void main(String[] args) {InputStream inputStream = System.in;OutputStream outputStream = System.out;InputReader in = new InputReader(inputStream);PrintWriter out = new PrintWriter(outputStream);Task solver = new Task();solver.solve(in, out);out.close();}static class Task {// ================= 代码实现开始 =================final int N = 5005;int[][] d = new int[N][N];int[][] f = new int[N][N];/* 请在这里定义你需要的全局变量 */// n个物品,每个物品有体积价值,求若扔掉一个物品后装进给定容量的背包的最大价值// n:如题// w:长度为n+1的数组,w.get(i)表示第i个物品的价值(下标从1开始,下标0是一个数字-1,下面同理)// v:长度为n+1的数组,v.get(i)表示第i个物品的体积// q:如题// qV:长度为q+1的数组,qV.get(i)表示第i次询问所给出的背包体积// qx:长度为q+1的数组,qx.get(i)表示第i次询问所给出的物品编号// 返回值:返回一个长度为q的数组,依次代表相应询问的答案List<Integer> getAnswer(int n, List<Integer> w, List<Integer> v, int q, List<Integer> qV, List<Integer> qx) {/* 请在这里设计你的算法 */// 丢弃的x之前的最大价值背包// 枚举n个物品// 计算前缀背包for (int i = 1; i <= n; i++) {// 由于是二维数组,需要做充填备忘// 对于i=1时,d[1][j] = d[0][j]// 对于i=2时,d[2][j] = d[1][j]for (int j = 0; j < v.get(i); j++) {d[i][j] = d[i-1][j];}// 01背包问题// 对于体积为v,价值为w的物品i,要装填到背包体积为j的背包中的最大价值// d[i-1][j]表示不放物品i,只放i之前的物品时所能装的最大价值// d[i-1][j-v.get(i)]+w.get(i) 表示放入物品i后,恰好装满背包,此时由没放物品i,背包体积为当前体积减去物品i体积的最大价值背包加上物品i的价值// 两者中较大者即为最大价值for (int j = v.get(i); j <= 5000; j++) {d[i][j] = Math.max(d[i-1][j],d[i-1][j-v.get(i)]+w.get(i));}}// 丢弃的x之后的最大价值背包// 与上面的过程相反,上面是依照物品正序求最大背包// 此处依照物品顺序倒序求最大背包// 计算后缀背包for (int i = n; i >= 1; i--) {for (int j = 0; j < v.get(i); j++) {f[i][j] = f[i+1][j];}for (int j = v.get(i); j <= 5000; j++) {f[i][j] = Math.max(f[i+1][j],f[i+1][j-v.get(i)]+w.get(i));}}List<Integer> ans = new ArrayList<>();for (int k = 1; k <= q; k++) {int x = qx.get(k),V = qV.get(k);// 最大值,将背包拆分成x之前的背包,和x之后的背包,所有组合中的背包和int mx = 0;for (int i = 0; i <= V; i++) {mx = Math.max(mx,d[x-1][i]+f[x+1][V-i]);}ans.add(mx);}return ans;}// ================= 代码实现结束 =================void solve(InputReader in, PrintWriter out) {int n, q;List<Integer> v = new ArrayList<>();List<Integer> w = new ArrayList<>();List<Integer> qv = new ArrayList<>();List<Integer> qx = new ArrayList<>();v.add(-1);w.add(-1);qv.add(-1);qx.add(-1);n = in.nextInt();for (int i = 0; i < n; ++i) {int a = in.nextInt(), b = in.nextInt();v.add(a);w.add(b);}q = in.nextInt();for (int i = 0; i < q; ++i) {int a = in.nextInt(), b = in.nextInt();qv.add(a);qx.add(b);}List<Integer> ans = getAnswer(n, w, v, q, qv, qx);for (int i = 0; i < q; ++i)out.println(ans.get(i));}}

习题课3-1(动态规划)相关推荐

  1. 计算机计组成原理课后,计算机组成原理课后习题课(0001).doc

    计算机组成原理课后习题课(0001).doc (7页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 19.90 积分 1.什么是指令周期?什么是机器周期? ...

  2. 通信原理2习题课汇总(随机信号、信道、最佳接收)

    写在前面:本文仅用于个人学习,授课教师为郭心悦,下面的ppt为郭老师上课课件. 文章目录 第二章:随机信号习题 第三章:信道习题课 第五章:数字信号最佳接收习题课 第二章:随机信号习题 自相关函数:离 ...

  3. c++求n的几次方_数理统计|笔记整理(E)——Ch7-C习题课

    上一节笔记传送门:数理统计|笔记整理(D)--Ch1-6习题课 -------------------------------------- 大家好!这一节我们依然会补充一些习题,内容则是正文的后半部 ...

  4. 谢惠民恽自求易法槐钱定边数学分析习题课讲义思考题练习题参考题解答

    谢惠民恽自求易法槐钱定边数学分析习题课讲义思考题练习题参考题解答. 见 http://www.cnblogs.com/zhangzujin/p/3527416.html 上册全部习题, 思考题, 参考 ...

  5. 谢惠民,恽自求,易法槐,钱定边编数学分析习题课讲义习题参考解答

    谢惠民,恽自求,易法槐,钱定边编数学分析习题课讲义16.2.3练习题参考解答[来自陶哲轩小弟] 谢惠民,恽自求,易法槐,钱定边编数学分析习题课讲义23.2.3练习题参考解答[来自陶哲轩小弟] 其他见: ...

  6. 化工原理 --- 流体流体 --- 习题课及复习

    第一部分 --- 习题课 1.R1左边那部分空白的高度的计算方法: 在一开始阀门关闭的时候,A和B处的压力是相等的,所以U形管中处处压力相等,液面都是持平的 但是当阀门打开后A和B处的压力就不相等了, ...

  7. 谢惠民恽自求易法槐钱定边数学分析习题课讲义第2版上册全部思考题练习题参考题解答...

    谢惠民恽自求易法槐钱定边数学分析习题课讲义第2版上册全部思考题练习题参考题解答. 需要的话请移步家里蹲大学数学杂志官方网站. 第9章及以前的采用的引用的方法. 就是 Latex 中会用 \cite, ...

  8. 幂级数和函数经典例题_10函数项级数和幂级数 习题课

    111 第十章 函数项级数习题课 一. 主要内容 1 .基本概念 函数列(函数项级数)的点收敛.一致收敛.内闭一致收敛.绝对收敛.和 函数 幂级数的收敛半径.收敛区间.收敛域 2 . 一致收敛性 A ...

  9. 幂级数和函数经典例题_函数项级数和幂级数 习题课

    111 第十章 函数项级数习题课 一. 主要内容 1 .基本概念 函数列(函数项级数)的点收敛.一致收敛.内闭一致收敛.绝对收敛.和 函数 幂级数的收敛半径.收敛区间.收敛域 2 . 一致收敛性 A ...

最新文章

  1. backbone学习总结(二)
  2. SNMP高速扫描器braa
  3. dotnet 将C#编译为wasm让前端html使用
  4. YBTOJ:采矿战略(线段树维护dp、树链剖分)
  5. 如何把通达信公式变成python_通达信附图如何改成选股公式?
  6. 互联网晚报 | 4月11日 星期一 | 苏州放宽住房限售;苹果确认开始在印度生产iPhone 13;民航局将上报民航专项检查方案...
  7. paascloud商城系统源码v2.0-完整购物流程和后端运营平台
  8. 包括循环和分支的C语言程序,《C语言程序设计》分支和循环的C程序设计.ppt
  9. OpenCV-python学习笔记(四)——smoothing and blurring平滑和模糊
  10. linux服务器配置与管理_一个十多年的系统管理员,忘了如何管理一台服务器
  11. php7 imagick扩展,php7如何安装imagick扩展
  12. cmd与服务器文件传输,渗透技巧--通过cmd上传文件的N种方法
  13. 修改数据库密码的多种方法
  14. FusionSphere 物理CPU与VCPU的关系梳理总结
  15. 丘成桐:数理与人文(官方完整版PDF下载)(公号回复“丘成桐数学”下载PDF典型资料,欢迎转发、赞赏支持科普)
  16. 电商网站商品详情架构
  17. PUSHmall推贴S2B2B2C模式-共享电商营销平台正式版
  18. nginx配置文件映射外网服务器
  19. 剑指 Offer 10- I. 斐波那契数列
  20. Google Mail

热门文章

  1. android如何释放图片缓存
  2. 【投屏】Scrcpy源码分析四(最终章 - Server篇)
  3. RestCloud 微服务监控中心
  4. 离散数学 传递闭包 Warshall算法
  5. AI值得信任吗?“可信AI”或能给出答案
  6. Django数据库学习——定义用户模型(实例)
  7. 股市学习稳扎稳打(四)当宏观经济出现复苏时,不同的行业分别以什么顺序进行轮动上涨
  8. java lambda表达式 list转string
  9. Java DOM4J解析String类型XML,Document对象转String
  10. 工程伦理和学术道德(2021秋)