动态规划

动态规划求最长公共子串

牧云@^-^@ 提交于 2020-03-01 10:03:46
动态规划原理 基本思想: 问题的最优解可以有子问题的最优解推导得到,可以先求子问题的最优解,再构造原问题的最优解。如果子问题有较多的重复出现,则可以自底向上从最终子问题向原问题逐步求解。适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。对于有些子问题被重复计算了很多次,我们能够保存已解决的子问题的答案,在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。我们可以用一个表来记录所有已解的子问题的答案。不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。这就是动态规划法的基本思路。 动态规划算法的设计步骤: 1、分析优化解的结构 2、递归的定义最优解的代价 3、自底向上的计算优化解的代价并保存,并获取构造最优解的信息 4、根据构造最优解的信息构造最优解 基本模型: (1)确定问题的决策对象。 (2)对决策过程划分阶段。 (3)对各阶段确定状态变量。 (4)根据状态变量确定费用函数和目标函数。 (5)建立各阶段状态变量的转移过程,确定状态转移方程。 状态转移方程的一般形式: 一般形式: U:状态; X:策略   顺推:f[Uk]=opt{f[Uk-1]+L[Uk-1,Xk-1]} 其中, L[Uk-1,Xk-1]: 状态Uk-1通过策略Xk-1到达状态Uk 的费用 初始f[U1];结果:f[Un]。 倒推:   f[Uk]=opt{f[Uk+1]

最大子序和(简单+进阶)

蹲街弑〆低调 提交于 2020-03-01 08:47:04
总共4种方法,有贪心法、分治法和动态规划,还有一种最笨的,分治法主要是把问题分成小问题进行解决,再对小问题的和进行综合处理,贪心法和动态规划法相同 简单 方法一:这个方法最愚蠢,用i,j当起始结束标志 int maxSubArray(int* nums, int numsSize){ int i,j,s,max=nums[0]; for(i=0;i<numsSize;i++){ s=0; for(j=i;j<numsSize;j++){ s+=nums[j]; if(s>max){ max=s; } } } return max; } 方法二:贪心法,涉及到三个变量,在当前位置的最大和cur_sum,整体最大和max_sum 1.首先设置在0位置,当前最大和为nums[0],题目要求子数组最少包含一个元素 2.当遍历到i位置,当前和是加上之前的元素大,还是只保留本元素大 3接着判断在当前元素的和是否大于max决定是否更新max int maxSubArray(int* nums, int numsSize){ int cur_sum=nums[0],max_sum=nums[0],i; for(i=0;i<numsSize;i++){ cur_sum=(cur_sum+nums[i])>nums[i]?(cur_sum+nums[i]):nums[i]; max_sum=cur

动态规划概述(4)总结

青春壹個敷衍的年華 提交于 2020-03-01 02:23:42
动态规划三大要素,三大特点 要素一:状态正确设定。 要素二:状态转移方程列正确。 要素三:最终获取的输出参数一定要选择正确。 特点一:最优子结构特点,每一个问题派生出的小问题一定拥有最用性特征。 特点二:最优性要求,有最优子结构组合而成的解一定满足最优性要求。 特点三:无后效性,目前的参数和获值,只与子问题有关,不与父节点有关。(逆推的时候只有父节点和此节点有关) 动态规划所解决的问题大部分是贪心和暴力枚举无法解决的,贪心容易掉入“贪心的陷阱”,因为贪心是一种“投机取巧”的方法,忽略了一些子问题,有些时候把不该忽略的子问题也忽略了。暴力容易超时,因为只能够枚举所有情况。 确切来说,DP,贪心,暴力,枚举,这四种方法都不能算为一种特殊算法,而是一种思想,因为这些方法没有确切的模板,就像方程一样,没有一个确切的最终方程能够包含所有情况的方程。 动态规划最简单的部分就结束了。 来源: CSDN 作者: 算法蒟 链接: https://blog.csdn.net/weixin_41568030/article/details/104581896

礼物(动态规划)

一曲冷凌霜 提交于 2020-02-29 11:22:33
   数据 题目大意:   已经很简洁了 题解:    在题目没有给出特殊约束的情况永远不要考虑对背包算法的优化    因为这是不可能的事       记录 \(f[i][j]\) 为前 \(i\) 个物品,花费 \(j\) 元取得的最大价值       记录 \(g[i][j]\) 为后 \(i\) 个物品,花费 \(j\) 元取得的最大价值       每次询问只要将 \(f[i-1]\) 和 \(g[i+1]\) 合并即可    AC代码 #include <cstdio> #include <algorithm> using namespace std; const int N=1e3+5; int n,Q,x,v,ans; int a[N],b[N],f[N][1005],g[N][1005]; inline int read(){ int x=0;char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x; } int main(){ n=read(); for(int i=1;i<=n;i++){ a[i]=read();b[i]=read(); int garbage=read(); } for

蓝桥杯 算法提高 最大值路径Python实现(动态规划)

十年热恋 提交于 2020-02-29 11:21:24
资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述   刷微博,编程序。如下图所示,@北京发布 提出了如下“头脑震荡”问题。对此问题做一般化描述:   有n阶方阵,从矩阵的左下角元素为起点,从行或列(水平或垂直)两个方向上移动,直到右上角。求出有多少条路径可以使得经过的元素累加值最大,最大值是多少。    输入格式   共有n+1行。   第一行整数n,表示矩阵的阶数,2<=n<=10。   第二行起,每行n个整数,以空格分隔,共n行。。 输出格式   一行,两个空格分隔的数,第一个表示最大值路径的条数,第二个表示最大值。 样例输入 5 4 5 4 5 6 2 6 5 4 6 2 6 6 5 2 4 5 2 2 5 5 2 5 6 4 样例输出 3 47 分析: 最大的路径肯定是要动态规划出来,我直接在输入的数组上面动态规划的,直接给出题给例子动规之后的结果: [ 17 , 31 , 35 , 40 , 47 ] [ 13 , 26 , 31 , 35 , 41 ] [ 11 , 20 , 26 , 31 , 33 ] [ 9 , 14 , 16 , 20 , 27 ] [ 5 , 7 , 12 , 18 , 22 ] 最左上角的数字就是最大的路径值。 需要我们搞定的是路径的数量。 就是从数组的右上角开始往下搜索,遇到左侧下方和正下方的数字一样的时候会兵分两路

动态规划之数字三角形举一反三

时间秒杀一切 提交于 2020-02-28 21:07:55
动态规划(一) 例题一、数字三角形(POJ1163) 在上面的数字三角形中寻找一条从顶部到底边的路径,使得路径上所经过的数字之和最大。路径上的每一步都只能往左下或右下走。只需要求出这个最大和即可,不必给出具体路径。 三角形的行数大于1小于等于100,数字为 0 - 99 输入格式: 5 //三角形行数。下面是三角形 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 要求输出最大和 解题思路: 用二维数组存放数字三角形。D( r, j) : 第r行第 j 个数字(r,j从1开始算)MaxSum(r, j) : 从D(r,j)到底边的各条路径中,最佳路径的数字之和。 问题:求 MaxSum(1,1) 典型的递归问题。 D(r, j)出发,下一步只能走D(r+1,j)或者D(r+1, j+1)。故对于N行的三角形: if ( r == N) MaxSum(r,j) = D(r,j) else MaxSum( r, j) = Max{ MaxSum(r +1,j), MaxSum(r+1,j+1) }+ D(r,j) 下面是简单的递归,但存存大量的重复计算。 # include <iostream> using namespace std ; # define Max 101 int D [ Max ] [ Max ] ; int n ; int MaxSum ( int i ,

动态规划——背包问题

倖福魔咒の 提交于 2020-02-28 15:17:10
在写博客之前,先列出两个背包九讲链接以供参考 yxc在B站上讲的背包九讲: 背包九讲专题 以及一篇非常经典的 dd大牛的《背包九讲》 0 1背包问题 完全背包问题 多重背包问题 分组背包问题 0 1背包问题 有N件物品和一个容量为V的背包。第i件物品的费用是c[i](本题里是v[i]),价值是w[i]。 这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。 在求状态转移方程的方面,思路是集合划分: f(i,j):“在i个东西里面选质量为j的东西的总商品价值”这一集合可分为“选的所有东西里面 不包含i ”和“选的东西里面 包含i ”两种情况。 的话 不含i的情况即是f(i-1,j)【在i-1个东西中选质量为j的东西】 含i的情况即是f(i-1,j-V i )+w i 【由于选了i,那就是在i-1个东西中选j-V i 质量的总价值加上i的价值】 将上述两个集合取价值最大的取法,即为“在i个东西里面选质量为j的东西的总商品价值” 优化1:减少操作次数 由于上述的情况中,含i的情况是不一定存在的(那是当背包最大重量j<V i 即装不下的时候不需要考虑) 优化2:将二维数组优化为滚动数组 滚动数组:如果f(i)的计算仅仅只用了f(i-1)来完成计算的话,就只需要开一个f[2][N]的数组即可(可以运用e=1-e来实现滚动) 值得注意的是

程序员必须掌握的核心算法有哪些?

风流意气都作罢 提交于 2020-02-27 18:24:21
一、算法最最基础 1、时间复杂度 2、空间复杂度 一般最先接触的就是时间复杂度和空间复杂度的学习了,这两个概念以及如何计算,是必须学的,也是必须最先学的,主要有最大复杂度、平均复杂度等,直接通过博客搜索学习即可。 文章推荐: 算法分析神器—时间复杂度 二、基础数据结构 1、线性表 列表(必学) 链表(必学) 跳跃表(知道原理,应用,最后自己实现一遍) 并查集(建议结合刷题学习) 不用说,链表、列表必须,不过重点是链表。 三分钟基础数据结构:如何轻松手写链表? 以后有面试官问你「跳跃表」,你就把这篇文章扔给他 2、栈与队列 栈(必学) 队列(必学) 优先队列、堆(必学) 多级反馈队列(原理与应用) 特别是优先队列,再刷题的时候,还是经常用到的,队列与栈,是最基本的数据结构,必学。可以通过博客来学习。相关文章: 三分钟基础知识:什么是栈? 二叉堆是什么鬼? 【算法与数据结构】堆排序是什么鬼? 3、哈希表(必学) 碰撞解决方法:开放定址法、链地址法、再次哈希法、建立公共溢出区(必学) 布隆过滤器(原理与应用) 哈希表相关的,推荐通过博客来学习,推荐文章: Hash冲突之开放地址法 4、树 二叉树:各种遍历(递归与非递归)(必学) 哈夫曼树与编码(原理与应用) AVL树(必学) B 树与 B+ 树(原理与应用) 前缀树(原理与应用) 红黑树(原理与应用) 线段树(原理与应用)

ARTS打卡第5周

孤街醉人 提交于 2020-02-27 17:14:52
A: Unique Paths II  Medium A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below). Now consider if some obstacles are added to the grids. How many unique paths would there be? An obstacle and empty space is marked as 1 and 0 respectively in the grid. 解析:一个机器人从起始位置到终点,只能选择向下或者向右,不能向左或者向上,一个有多少种不同的路线,遇到障碍时无法通过 解题思路:使用动态规划的方式来进行题目的解答,可以画出相应的网格图 4行4列时: 当行数为1时:机器人只能向右走,列数为i,每个array[0][i

动态规划:最长递增子序列

大兔子大兔子 提交于 2020-02-27 13:25:56
题目描述 计算最少出列多少位同学,使得剩下的同学排成合唱队形 说明: N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足存在i(1<=i<=K)使得T1<T2<......<Ti-1<Ti>Ti+1>......>TK。 你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。 输入描述: 整数N 输出描述: 最少需要几位同学出列 输入 8 186 186 150 200 160 130 197 200 输出 4 思路 两遍最长递增子序列,第一遍从左往右,第二遍从右往左,然后把两遍动态规划的结果相加,取最大的那个,比如8 186 186 150 200 160 130 197 200,第一遍dp的结果是 1 1 1 2 2 1 3 4,第二遍dp的结果为3 3 2 3 2 1 1 1,那么相加最大是5,所以需要出列的同学个数就是8-5+1=4.代码如下: 1 #include<iostream> 2 #include<vector> 3 using namespace std; 4 int main() { 5 int n; 6 while(cin>>n){ 7 int max