动态规划算法

合并类动态规划——石子合并(洛谷1880)

一世执手 提交于 2019-12-23 13:41:23
题目描述 Description 在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。 试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分. 输入输出格式 Input/output 输入格式: 数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数. 输出格式: 输出共2行,第1行为最小得分,第2行为最大得分. 输入输出样例 Sample input/output 样例测试点#1 输入样例: 4 4 5 9 4 输出样例: 43 54 来源:NOI 1996 代码: var n,i,j,k,l,minf,maxf:longint; a,s:array[0..300] of longint; f:array[1..300,1..300] of longint; function min(x,y:longint):longint; begin if x<y then exit(x) else exit(y); end; function max(x,y:longint):longint; begin if x>y then exit(x) else exit(y); end; begin readln(n); for i:=1 to n

LeetCode 72.编辑距离(动态规划)

Deadly 提交于 2019-12-20 16:13:39
编辑距离 针对两个字符串(如英文字母)的差异程度的量化测量,量测方式是看至少需要多少次的处理才能将一个字符串变成另一个字符串。 编辑距离应用 一、可应用于NLP,如拼写检查可以根据一个拼错的字和其他正确的字的编辑距离,判断哪一个(或哪几个)是比较可能的字。 二、编辑距离可以用在生物信息学,判断两个DNA的类似程度。 算法基本原理 用d[i,j]个步骤,表示串是s[1,…,i]转换为t[1,…,j]所需要的最少步骤的次数。我们要想得到s[1,…,i]经过最少次数的增加、删除、替换变成t[1,…,j],那么我们就必须在之前可以以最少次数的增加、删除、替换,使得串s和串t只需要再做一次操作或者不做就可以完成s[1,…,i]到t[1,…,j]的转换。 d[i][j]实现有三种方法 1、第一个单词的前i位变成第二个单词的前j-1位,然后再插入一个字符(d[i][j-1]+1) 2、第一个单词的前i-1位变成第二个单词的前j位,然后再删去一个字符(d[i-1][j]+1) 3、第一个单词的前i-1位变成第二个单词的前i-1位,然后替换最后一个字符,如果最后一个字符相同,就不用替换,反之,如果不同就替换最后一位(d[i-1][j-1] + 1) 代码如下: class Solution : def minDistance ( self , word1 , word2 ) : n = len (

动态规划0-1背包问题

你。 提交于 2019-12-16 21:29:10
最近看了一些简单的动态规划方面的例题 在学习的过程中发现 有的问题虽然不难 但是第一次看还是会有些问题 所以把自己弄0-1背包的问题拿出来给大家分享 不喜勿喷 网上资源特别多 讲解什么的就算了 其他人画的图都不错 递推关系 : 设所给 0-1 背包问题 的最优值为 m(i , j) ,即 m(i , j) 是背包容量为 j ,可选择物品为 i , i+1 , … , n 时 0-1 背包问题的最优值。由 0-1 背包问题的最优子结构性质,可以建立计算 m(i , j) 的递归式 : 上 式此时背包容量为 j ,可选择物品为 i 。此时在对 xi 作出决策之后 , 问题处于两种状态之一 : (1) 背包剩余容量是 j, 没产生任何效益; (2) 剩余容量 j-wi, 效益值增长了 vi ; 我写的代码 看完看有没有启发 package org.bq.dp; /** * 0-1背包问题 * * @author 白强原创 * @version 1.0 */ public class OneZero { // 最大背包容量 private static final int M = 10; // 物品数量 private static final int N = 3; // 物品重量数组 给它数组前面加一个0项是为了更好的表达这种关系 比方从一个到全部物品的时候i=2的使用w[i]

【算法】动态规划

假装没事ソ 提交于 2019-12-13 13:33:40
1.解决什么类型问题 1.1 计数问题 如最典型的 青蛙跳, 也就是斐波那契数列、 棋盘路径问题、 还有组合公式,不重复组合( Combination ), c(n, m) 从n个选手中选出m个出道~(101哈哈哈哈哈),有多少种可能性?这个问题可以分解为两个子问题,根据最后一个人能不能进组合有两种可能: 最后一个人出道,剩余席位是m-1, 子问题是 c(n-1, m-1) 最后一个人不能出道,剩余席位还是m,子问题是 c(n-1,m) c(n, m) = { c(n-1, m-1) + c(n-1, m) , if n > 1 and m > 1 and n >= m { n , if m = 1 { 1 , if n = 1 这一类问题通常 递推公式 是 子问题的和,c(n, m) =c(n-1, m-1) + c(n-1, m) , 边界 就是m=1或者n=1。 1.2 极值问题 如 背包问题, 就是多 阶段 最优决策。一般由初始状态开始,通过对中间阶段决策的选择,达到结束状态。这些决策形成了一个决策序列,同时确定了完成整个过程的一条决策路径。 初始状态→│决策1│→│决策2│→…→│决策n│→结束状态 如 棋盘最大和 (最小和),从(0,0) 到 (n-1,n-1)路上数值最大和 这一类问题通常递推公式是子问题max、min值,如上题 c[i][j] = max (c[i

算法与数据结构10-动态规划

跟風遠走 提交于 2019-12-10 22:44:39
动态规划:   一维动态规划:     目前我们所见到的DP问题都是1D的,让我们看一下其他例子: 问题描述1:给定n,找到不同的n写成1,3,4相加的方法   例如:n=5,答案是6   答案:公式:Dn = Dn-1 +Dn-3 +Dn-4      D[0] = D[1]=D[2] D[3]=2      for (i=4;i<=n;i++){        D[i] = D[i-1]+D[i-3]+D[i-5]      }   问题描述2:     假设你是一个职业拿钱犯,你打算拿一个街道的钱。每个房子里有定数量的钱。限定你的唯一条件是相邻的房子安保系统是相连的,如果拿相邻的房子就会惊动警察。     给定一个非负整数的列表代表每个房子当中的钱,计算在不惊动警察的情况下你可以拿到最多的钱。   答案:定义公式Yes(i) = 当前抢这个房子得到的最大值 No(i)=当前不抢这个房子得到的最大值     得到规律: Yes(i) = No(i-1)+a[i]          No[i] =max(Yes[i-1], No[i-1])          Yes[1] = a[1] Yes[2] = No[1]+a[2]          No[1] = 0 No[2] = max(Yes[1],No[1])          result: max(Yes[i], No[i

剑指offer 字符串的排列

霸气de小男生 提交于 2019-12-10 10:45:20
这是一道全排列的问题,具体的步骤百度可以找到很多。 算法思想是依次固定每一个字符然后对字串进行相同的操作即可 注意:这里的固定其实就是交换的意思,每次从begin位置开始依次往后交换str[begin] 与 str[i] 我觉的这是 动态规划 + 回溯 的算法题 最后想吐槽以下牛客的这个判题系统有点..... 来源: https://www.cnblogs.com/jiguang321/p/12014967.html

【动态规划】(不可以重复取)最小邮票数

拜拜、爱过 提交于 2019-12-07 12:23:25
时间限制:1秒 空间限制:65536K 热度指数:8840 算法知识视频讲解 校招时部分企业笔试将禁止编程题跳出页面,为提前适应,练习时请使用在线自测,而非本地IDE。 题目描述 有若干张邮票,要求从中选取最少的邮票张数凑成一个给定的总值。 如,有1分,3分,3分,3分,4分五张邮票,要求凑成10分,则使用3张邮票:3分、3分、4分即可。 输入描述: 有多组数据,对于每组数据,首先是要求凑成的邮票总值M,M<100。然后是一个数N,N〈20,表示有N张邮票。接下来是N个正整数,分别表示这N张邮票的面值,且以升序排列。 输出描述: 对于每组数据,能够凑成总值M的最少邮票张数。若无解,输出0。 示例1 输入 10 5 1 3 3 3 4 输出 3 状态转移关系: if(j < a[i]) dp[i][j] = dp[i-1][j]; else dp[i][j] = min(dp[i-1][j], dp [i-1] [j-a[i]] + 1); 注意不是 else dp[i][j] = min(dp[i-1][j], dp [i] [j-a[i]] + 1); 因为不可以重复取 #include<bits/stdc++.h> using namespace std; int main(){ int target; while(cin >> target){ int n; cin >> n

算法笔记——【动态规划】矩阵连乘问题

自古美人都是妖i 提交于 2019-12-07 04:43:51
问题描述 :给定n个矩阵:A 1 ,A 2 ,...,A n ,其中A i 与A i+1 是可乘的,i=1,2...,n-1。确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。输入数据为矩阵个数和每个矩阵规模,输出结果为计算矩阵连乘积的计算次序和最少数乘次数。 问题解析 :由于矩阵乘法满足结合律,故计算矩阵的连乘积可以有许多不同的计算次序。这种计算次序可以用加括号的方式来确定。若一个矩阵连乘积的计算次序完全确定,也就是说该连乘积已完全加括号,则可以依此次序反复调用2个矩阵相乘的标准算法计算出矩阵连乘积。 完全加括号的矩阵连乘积可递归地定义为: (1)单个矩阵是完全加括号的; (2)矩阵连乘积A是完全加括号的,则A可表示为2个完全加括号的矩阵连乘积B和C的乘积并加括号,即A=(BC) 例如,矩阵连乘积A 1 A 2 A 3 A 4 有5种不同的完全加括号的方式:(A 1 (A 2 (A 3 A 4 ))),(A 1 ((A 2 A 3 )A 4 )),((A 1 A 2 )(A 3 A 4 )),((A 1 (A 2 A 3 ))A 4 ),(((A 1 A 2 )A 3 )A 4 )。每一种完全加括号的方式对应于一个矩阵连乘积的计算次序,这决定着作乘积所需要的计算量。 看下面一个例子,计算三个矩阵连乘{A 1 ,A 2 ,A 3 };维数分别为10*100

动态规划之——最长公共子串和矩阵链乘法

拜拜、爱过 提交于 2019-12-06 14:52:06
1. 最长公共子串 最长公共子串与最长公共子序列有一些类似,只不过这里子串要求是连续的。 这里我们定义 lcs[i][j] 表示 以 s[i] 与 t[j] 为末尾元素 的最长公共子串长度,那么我们有: \[lcs[i][j] = \begin{cases} lcs[i-1][j-1]+1 &\text{如果 } s[i] == t[j] \\ 0 &\text{如果 } s[i] != t[j] \end{cases}\] import numpy as np s = 'mitcmu' t = 'mtacmu' def longest_commom_substr(s, t): m = len(s) n = len(t) lcs = np.zeros((m, n), 'uint8') max_lcs = 0 for i in range(0, n): if s[0] == t[i]: lcs[0][i] = 1 else: lcs[0][i] = 0 for i in range(0, m): if s[i] == t[0]: lcs[i][0] = 1 else: lcs[i][0] = 0 for i in range(1, m): for j in range(1, n): if s[i] == t[j]: lcs[i][j] = lcs[i-1][j-1] + 1 max

从一道动态规划到卡特兰数

不羁的心 提交于 2019-12-06 09:58:34
从一道动态规划到卡特兰数 LeetCode 96 题目链接: https://leetcode-cn.com/problems/unique-binary-search-trees/ 题意:给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种? n = 3 时: 动态规划 思路:从 1 开始到 n ,每次以这个数为根,左子树存放比它小的数,右子树存放比它大的数。每个根不重复,因此每个树也必定不重复。 左子树和右子树,又可以按照这个规则去生成新的树。 例如:n = 3的时候 1为根: 比 1 小的数只有 0,不用管。比 1 大的数有 2 和 3。 拿 2 和 3 来生成一棵树和拿 1 和 2 来生成一棵树的种数是不是相同的?那么 1 和 2 能生成多少种树呢? 2为根: 比 2 小的是 1,比 2 大的是 3。这里只有 1 种。 3为根: 比 3 小的是 1 和 2,1 和 2 能生成多少种树呢? 我们先暂停思维,来到一个新的问题。 n = 2 的时候,结果应该是多少? n = 2 的时候,按照我们之前的方法。 1 为根:比 1 大的数只有 2, 这里有 1 种。 2 为根:比 2 小的数只有 1, 这里有 1 种。 那答案就应该是 2 种。 解决了 n = 2 的问题,那 n = 3 的问题就也解决了。 ans = 2 + 1 + 2 = 5。 我们来看一般情况