动态规划算法

算法第三章作业

戏子无情 提交于 2019-12-03 08:08:00
1.对动态规划的理解 一转眼,第三章学完了,总体感觉真的是难理解,不过一旦理解了其中的做法就能很好的模仿动态规划解法了,经过考前的临阵磨刀,终于对填表发有了较深刻的理解了,通过上一问题的解来解出下一问题的解,其实也说不上有多巧妙,填表发也就是不过如此,我们需要做的是如何找到问题的递归方程,总之,第三章收获填表发,还算不错 2.最长递增子序列 m[i] = max{m[k]+1 | a[k]<a[i]}(1<=k<i) 租用游艇 m[i] = min{c[i][k]+m[k[} (i<k<=n) 表示第i到终点的最小费用 3.结对编程情况 通过上次的上机测试,队友也对我说了有所收获,期望队友能花多些时间学习码字,总之就是再接再厉! 来源: https://www.cnblogs.com/liyuan1/p/11784506.html

动态规划

时光总嘲笑我的痴心妄想 提交于 2019-12-03 07:26:32
一.特性: (1)最优子结构性质。即问题的最优解所包含的子问题的解也是最优的。 (2)子问题重叠性质。在用递归算法自顶向下对问题进行求解时,每次产生的子问题并不总是新问题, 有些子问题会被重复计算多次,利用子问题的重叠性质,对于每个子问题只计算一次,然后将结果保存 起来,下次需要重新计算已经计算过的的问题查询结果即可。 (3)无后效性:每个状态都是过去历史的一个完整总结。 二.Dp分类 简单的Dp: (1)递推:一般形式单一,从前往后分类枚举即可。 (2)背包:0-1背包、完全背包、分组背包、多重背包 (3)LIS:最长递增子序列,朴素的LIS是复杂度为O(n 2 )的算法,二分下的LIS是复杂度O(nlog 2 n)的算法。 (4)LCS:最长公共子序列,通常时间复杂度为O(n 2 )的算法 区间Dp: 枚举将区间分成左右两部分,然后求出左右区间再合并。 树形Dp: 基于在树上的数据结构,通过DFS维护从根到叶子或从叶子到根的状态转移 三.解题三部曲 第一步:确定状态 第二部:确定状态转移方程 第三步:确定编程实现方式 问题1:令 I 是一个 n 位十进制整数,如果将 I 划分为 k 段,可得到 k 个整数。这 k 个整数的乘积称为 I 的一个 k 乘积。对于给定的 n 、k 和 I,求出 I 的最大 k 乘积。 (一):确定状态:dp[ i ][ j ]: 表示前 i 个数

动态规划:双处理机调度问题(独立任务最优调度问题)

北城余情 提交于 2019-12-03 04:18:19
问题描述 假设房前有两个处理机A、B,以及n个待处理的任务。第i个任务在处理处理机A上处理需要的时间为a i ,在处理机B上处理的时间为b i ,两个处理机可以并行处理任务,但单个处理机不能同时执行任务。要求给定n个任务及各个任务对应的a i 、b i ,求得顺序完成这些任务所需要的 最短时间 。 思路分析 一个问题能否使用动态规划算法最主要的是确定它是否具有 最优子结构性质 ,在证明最优子结构性质之后,再去找到状态转移方程,之后问题就简单多了。 对于这个问题,我们可以考虑,当完成第k个任务时,有两种可能: 一是 A处理机完成了第k个任务,那么B处理机完成k个任务的最短时间就与B处理机完成k-1个任务所需的最短时间是相同的 二是 B处理机完成了第k个任务,那么B处理机完成k个任务的最短时间就等于B处理机完成k-1个任务的最短时间加上B处理机完成第k个任务所需要的时间 设F[k][x]表示完成第k个任务时A耗费的时间为x的情况下B所花费的最短时间,其中0<=k <= n, 0<=x<= Σa i ,那么,状态转移方程为 \[ F[k][x] = min{F[k-1][x-a_k], F[k-1][x] + b_k} \] 处理好特殊情况(如x小于0时)开始填表即可。 最终的结果即是完成n个任务时A和B所需时间的较大值,即 max(F[n][x], x) .

【动态规划】01背包问题_两种解法

…衆ロ難τιáo~ 提交于 2019-12-03 00:30:15
问题描述 0-1背包问题:给定 \(n\) 种物品和一背包。物品i的重量是 \(w_i\) ,其价值为 \(v_i\) ,背包的容量为 \(C\) 。问:应该如何选择装入背包的物品,使得装人背包中物品的总价值最大? 在选择装人背包的物品时,对每种物品 \(i\) 只有两种选择,即装人背包或不装入背包。不能将物品 \(i\) 装入背包多次,也不能只装入部分的物品 \(i\) 。因此,该问题称为 0-1背包问题 。 此问题的形式化描述是,给定 \(C>0\) , \(w_i>0\) , \(v_i>0\) , \(1≤i≤n\) ,要求找出 \(n\) 元0-1向量 \((x_1,x_2,\cdots,x_n), x_i\in\{0,1\},1 \leq i \leq n\) ,使得 \(\sum_{i=1}^{n} w_ix_i \leq C\) ,而且 \(\sum_{i=1}^{n} v_ix_i\) 达到最大。因此,0-1背包问题是一个特殊的整数规划问题。 \[max\sum_{i=1}^{n} v_ix_i\] \[\left\{\begin{matrix} \sum_{i=1}^{n} w_ix_i \leq C & \\ x_i\in\{0,1\}, & 1 \leq i \leq n \end{matrix}\right.\] 最优子结构性质 0

用动态规划算法解决TSP问题

匿名 (未验证) 提交于 2019-12-03 00:30:01
环境:程序使用语言java,jdk版本1.8,程序中用到的jar包:poi-3.17 程序中使用的数据:下载地址: https://download.csdn.net/download/qq_35685675/10487174 项目导入: 3.实验主要源代码 City.java//城市类,结构体 package public class private int name ; private double X ; private double Y ; public int name double x double y ) { super (); this . name name -1; X x ; Y y ; } public int return name ; } public void int name ) { this . name name ; } public double return X ; } public void double x ) { X x ; } public double return Y ; } public void double y ) { Y y ; } @Override public return "city [name=" name ",X=" X ", Y=" Y "]" ; } } inputData.Java//导入数据类

动态规划:双处理机调度问题(独立任务最优调度问题)

匿名 (未验证) 提交于 2019-12-03 00:15:02
假设房前有两个处理机A、B,以及n个待处理的任务。第i个任务在处理处理机A上处理需要的时间为a i ,在处理机B上处理的时间为b i ,两个处理机可以并行处理任务,但单个处理机不能同时执行任务。要求给定n个任务及各个任务对应的a i 、b i ,求得顺序完成这些任务所需要的 最短时间 。 一个问题能否使用动态规划算法最主要的是确定它是否具有 最优子结构性质 ,在证明最优子结构性质之后,再去找到状态转移方程,之后问题就简单多了。 对于这个问题,我们可以考虑,当完成第k个任务时,有两种可能: 一是 A处理机完成了第k个任务,那么B处理机完成k个任务的最短时间就与B处理机完成k-1个任务所需的最短时间是相同的 二是 B处理机完成了第k个任务,那么B处理机完成k个任务的最短时间就等于B处理机完成k-1个任务的最短时间加上B处理机完成第k个任务所需要的时间 设F[k][x]表示完成第k个任务时A耗费的时间为x的情况下B所花费的最短时间,其中0<=k <= n, 0<=x<= ∑a i ,那么,状态转移方程为 \[ F[k][x] = min{F[k-1][x-a_k], F[k-1][x] + b_k} \] 处理好特殊情况(如x小于0时)开始填表即可。 最终的结果即是完成n个任务时A和B所需时间的较大值,即 max(F[n][x], x) . 最重要的就是想明白状态转移方程代表的是什么

递归与动态规划的异同

匿名 (未验证) 提交于 2019-12-03 00:04:02
递归和动态编程(Dynamic Programming, DP)是算法类问题中的难点所在。算法的核心在于找到状态转移方程,即如何通过子问题解决原问题。 相似 递归和动态编程能解决的问题都有一个特性:原问题(problem)可以分解成若干个子问题(sub-problem),只有先解决了子问题才能进一步解决原问题。子问题的解决方式形式上与原问题一致。 区别 DP和递归有什么不同?最大的区别在于,DP 存储子问题的结果 ,当子问题已经被计算过,直接返回结果。因此,当需要重复计算子问题时,DP的时间效率高很多,但 需要额外的空间 。 递归的时间成本随递归深度n(单条路径中递归调用的次数)成指数增长;空间复杂度为O(n)。 动态编程的核心在于,如果在一个问题的解决方案中,子问题被重复计算,那么就可以利用记录中间结果,达到用空间换取时间的目的。 什么是动态规划 来源:51CTO 作者: QilanAllen 链接:https://blog.csdn.net/QilanAllen/article/details/100805998

背包九讲

匿名 (未验证) 提交于 2019-12-02 22:56:40
背包九讲 前言 本篇文章是我(dd_engi)正在进行中的一个雄心勃勃的写作计划的一部分,这个计划的内容是写作一份较为完善的NOIP难度的动态规划总结,名为《解动态规划题的基本思考方式》。现在你看到的是这个写作计划最先发布的一部分。 背包问题是一个经典的动态规划模型。它既简单形象容易理解,又在某种程度上能够揭示动态规划的本质,故不少教材都把它作为动态规划部分的第一道例题,我也将它放在我的写作计划的第一部分。 读本文最重要的是思考。因为我的语言和写作方式向来不以易于理解为长,思路也偶有跳跃的地方,后面更有需要大量思考才能理解的比较抽象的内容。更重要的是:不大量思考,绝对不可能学好动态规划这一信息学奥赛中最精致的部分。 Ŀ¼ 第一讲 01背包问题 这是最基本的背包问题,每个物品最多只能放一次。 第二讲 完全背包问题 第二个基本的背包问题模型,每种物品可以放无限多次。 第三讲 多重背包问题 每种物品有一个固定的次数上限。 第四讲 混合三种背包问题 将前面三种简单的问题叠加成较复杂的问题。 第五讲 二维费用的背包问题 一个简单的常见扩展。 第六讲 分组的背包问题 一种题目类型,也是一个有用的模型。后两节的基础。 第七讲 有依赖的背包问题 另一种给物品的选取加上限制的方法。 第八讲 泛化物品 我自己关于背包问题的思考成果,有一点抽象。 第九讲 背包问题问法的变化 试图触类旁通、举一反三。 附

动态规划算法

匿名 (未验证) 提交于 2019-12-02 22:56:40
动态规划思想 通过状态转移方程将大问题分解为小问题,找到小问题的最优解,然后基于此小问题的最优状态获得另一问题的最优解。具体做法是将各个小问题的最优解存入数组中,然后基于其来获取当前问题的最优解。 在应用中就是找规律,将此规律用状态转移方程来表示。 以下通过例题来学习此算法!!! 题目一: 有1,3,5三种面值的硬币,找到总值为16元的最少硬币数量? 获得d(0)、d(1)、d(2)小问题的最优解 d(0) = 0 d(2) = d(2-1)+1 = d(1)+1 = 1+1 = 2 d(3) = d(3-3)+1 = d(0)+1 = 1 d(3) = d(3-1)+1 = d(2)+1 = 3 d(4) = d(4-3)+1 = d(1)+1 = 2 状态转移方程: d(x) = min( d(x-v)+1 ) #include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { //面值 int v[3] = { 1,3,5 }; //索引为总值,元素为硬币数量 vector<int> arr1; arr1.push_back(0); for (int i = 1; i <= 16; i++) { //所有面值对应的硬币数量 vector<int> arr2;

动态规划之石子合并一(Java 版本)

喜欢而已 提交于 2019-12-02 20:41:25
题目描述 有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。 输入 有 多组 测试数据,输入到文件结束。 每组测试数据第一行有一个整数n,表示有n堆石子。 接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开。 输出 输出总代价的最小值,占单独的一行。 样例输入 3 1 2 3 7 13 7 8 16 21 4 18 样例输出 9 239 题目解析: 本题是直线型的石子合并,我们可以采用 贪心算法 ,只要每一次都合并两个最小的石子堆,那么最后得到的总代价必然最小。其中,我们需要用一个sum数组保存不同区间石子堆的和,另外设一个dp二维数组,用来记录总代价, 我们假设i<j,则dp[i][j]等于[i,j]区间的石子和sum加上[i,j]区间的最优化石子合并解 ,得到的状态方程如下: 参考代码如下: import java.util.Arrays; import java.util.Scanner; /** * 石子合并 * @author autumn_leaf * @Date 2019/03/21 */ public class CombinStones { static int max =