动态规划

动态规划0—1背包问题

百般思念 提交于 2019-12-26 12:10:41
动态规划0-1背包问题 Ø 问题描写叙述: 给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。问应怎样选择装入背包的物品,使得装 入背包中物品的总价值最大? Ø 对于一种物品,要么装入背包,要么不装。所以对于一种物品的装入状态能够取0和1.我们设物品i的装入状态为xi,xi∈ (0,1),此问题称为0-11背包问题。 过程分析 数据:物品个数n=5,物品重量w[n]={0,2,2,6,5,4},物品价值V[n]={0,6,3,5,4,6}, (第0位,置为0,不參与计算,仅仅是便于与后面的下标进行统一,无特别用处,也可不这么处理。)总重量c=10. Ø背包的最大容量为10,那么在设置数组m大小时,能够设行列值为6和11,那么,对于m(i,j)就表示可选物品为i…n背包容量为j(总重量)时背包中所放物品的最大价值。 以下是自己写的源代码: #include<stdio.h> #include<stdlib.h> #include<iostream> #include<queue> #include<climits> #include<cstring> using namespace std; const int c = 10; //背包的容量 const int w[] = {0,2,2,6,5,4};//物品的重量,当中0号位置不使用 。 const int

动态规划--最长上升子序列(Longest increasing subsequence)

不羁岁月 提交于 2019-12-26 12:04:27
  前面写了最长公共子序列的问题。然后再加上自身对动态规划的理解,真到简单的DP问题很快就解决了。其实只要理解了动态规划的本质,那么再有针对性的去做这方的题目,思路很快就会有了。不错不错~加油    题目描述: POJ2533   给出一个数列,找出这个数列中最长上升子序列中所包含的个数。   解题思路:   DP 问题解题的一般方法就是自下而上,即先求解小的问题,然后再根据小的问题来解决大的问题,最后得到解。但是这里还要满足的条件是最优子结构,即最优解包含着其子问题的最优解。   那么我们首先用arr[]数组(从0下标开始)存储要求的数列,用longest_num[i]数组来记录以i为结尾的子序列里面包含的最长上升子序列的数字个数。然后用循环控制,从下标为1开始求longest_num,并且记录找到的最大值,即可得到解。在我的程序里面,我还加了一个功能就是把最长上升子序列打印出来,如果存在有多个的话,那么就只打印最后一个。   最后根据下面的DP方程就可以进行求解了:   longest_num[i] = max{longest_num[j] + 1,longest_num[i]} 其中j < i && arr[j] < arr[i]   程序:    #include <stdio.h> #define MAX_N 1001 int arr[MAX_N]; int

第14题:剪绳子

爱⌒轻易说出口 提交于 2019-12-25 11:26:50
// 题目:给你一根长度为n绳子,请把绳子剪成m段(m、n都是整数,n>1并且m≥1)。 // 每段的绳子的长度记为k[0]、k[1]、……、k[m]。k[0]*k[1]*…*k[m]可能的最大乘积是多少?例如当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到最大的乘积18。 考点 1.动态规划 :时间复杂度:O(N^2) 空间复杂度:O(n) 1.1 寻找一个问题的最优解 1.2 整体问题的最优解依赖各个子问题的最优解 1.3 各个子问题之间还有重叠的更小子问题 1.4 从上向下分析问题,从下往上求解问题。把已解决的子问题的最优解保存在数组中。 数学表示:f(n)=max(f(i)*f(n-i)),0<i<n 2.贪婪算法: 贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。当然,希望贪心算法得到的最终结果也是整体最优的。虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。如单源最短路经问题,最小生成树问题等。在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。 贪心算法求解的问题一般具有两个重要性质:贪心选择性质和最优子结构性质。 (1)所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优解的选择,即贪心选择来达到

使用动态规划实现正则表达式匹配

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-25 08:37:25
严正声明:本文系作者davidhopper原创,未经许可,不得转载。 下述问题来源于 正则表达式匹配 : 一、问题描述 给定一个字符串 s 和一个字符串模式 p ,请你来实现一个支持 . 和 * 的正则表达式匹配。 . 匹配 任意单个 字符 * 匹配 零个或多个 前面的那一个元素 所谓匹配,是要涵盖 整个字符串 s ,而不是部分字符串。 说明: s 可能为空,且只包含从 a-z 的小写字母。 p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 * 。 示例 1: 输入: s = "aa" p = "a" 输出: false 解释: "a" 无法匹配 "aa" 整个字符串。 示例 2: 输入: s = "aa" p = "a*" 输出: true 解释: 因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。 因此,字符串 "aa" 可被视为 'a' 重复了一次。 示例 3: 输入: s = "ab" p = ".*" 输出: true 解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。 首先,".*"匹配'a',接下来".*"匹配' b'。 示例 4: 输入: s = "aab" p = "c*a*b" 输出: true 解释: 因为 '*' 表示零个或多个,这里 'c' 为 0 个, 'a' 被重复一次

动态规划之0-1背包问题

时光总嘲笑我的痴心妄想 提交于 2019-12-25 07:30:40
给定n个物品和一个背包,物品i的重量是wi,其价值是vi,背包的容量为w,及最大载重量不超过W,在限定的总重量W内,我们如何选择物品,才能使物品的总价值最大。 具体问题: 有编号分别为a,b,c,d,e的五件物品,它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,现在给你个承重为10的背包,如何让背包里装入的物品具有最大的价值总和? m(i,j)表示当前背包的容量为j,可选择的物品范围为i,i+1,i+2....n。所以背包问题的递推式如下 m(i,j)={max{ m(i+1,j) ,m(i+1,j-w[i])+v[i]}(wi<=j), m(i+1,j)(wi>j)};( 但看公式还是比较抽象的 ) 下面具体的分析 现在我们才去的分析方法是从左往右,从下往上。 首先动态规划过程的表如下 这张表是从下往上从左往右的分析 当i=5时表示当前只有e一个物体,j从1到10慢慢增加表示背包容量在不断的增大,当j<=3的时候,背包的当前容量是小于e的,所以此时不能将物品加入到背包当中。当j>=4的时候恰好只有一个e所以背包最大为6。 当i=1,j=8的时候m[2][8]=9(不加上a),当加上a之后之后m[i+1][j-w[i]]+v[i]=m[2][6]+v[1]= 9+6=15.根据前面的公式m[i][j]=m[1][8]=15/其他的分析也是一样的

72. 编辑距离

怎甘沉沦 提交于 2019-12-23 03:11:05
链接 题目 . 难度: high 解答: 乍一看无从下手,可是我们有万能的动态规划。推导公式就是,当目标字符串增加一个字符的时候需要怎么根据之前的结果得到当前值。完全就是动态规划经典问题:寻找最长公共字符串的翻版 package main import "fmt" func minDistance ( word1 string , word2 string ) int { if len ( word1 ) == 0 { return len ( word2 ) } if len ( word2 ) == 0 { return len ( word1 ) } dp := make ( [ ] [ ] int , len ( word1 ) + 1 ) for i := 0 ; i <= len ( word1 ) ; i ++ { dp [ i ] = make ( [ ] int , len ( word2 ) + 1 ) } for i := 1 ; i <= len ( word1 ) ; i ++ { dp [ i ] [ 0 ] = i } for j := 1 ; j <= len ( word2 ) ; j ++ { dp [ 0 ] [ j ] = j } for i := 1 ; i <= len ( word1 ) ; i ++ { for j := 1 ; j

LeetCode 62.不同路径(动态规划)

牧云@^-^@ 提交于 2019-12-22 03:54:12
题目描述 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。 问总共有多少条不同的路径? 例如,上图是一个7 x 3 的网格。有多少可能的路径? 说明:m 和 n 的值均不超过 100。 思路 机器人只能向下或者向右移动一步,那么对于任意的i, j机器人只能从左侧或上方移动过来,特别的对于上边界或左边界,机器人只有一种移动方式。那么就有下面公式: ![在这里插入图片描述](https://img-blog.csdnimg.cn/20191221184946168.png 代码 class Solution : def uniquePaths ( self , m : int , n : int ) - > int : dp = [ [ 0 ] * ( n + 1 ) for i in range ( m + 1 ) ] dp [ 1 ] [ 0 ] = 1 for i in range ( 1 , m + 1 ) : for j in range ( 1 , n + 1 ) : dp [ i ] [ j ] = dp [ i - 1 ] [ j ] + dp [ i ] [ j - 1 ] return dp [ m ] [ n ] test =

Happy birthday 动态规划(三维数组)

北城余情 提交于 2019-12-22 01:35:07
题目大意:过生日,有一个N*M的表格,每个位置都有一块一定重量的蛋糕你可以选择吃完或者不吃,从(1,1)走到(n,m),每次只能向右走或向下走,最多能吃k重量的蛋糕。问你最多能吃多少蛋糕。 题目思路:之前的01背包我们都是用一维数组v[i]来储存的,但这次要用二维数组Map[i][j]储存一个点的价值,当前点由Map[i][j-1]或Map[i-1][j]走到。 # include <iostream> # include <algorithm> # define MAX 105 using namespace std ; int dp [ MAX ] [ MAX ] [ MAX ] , Map [ MAX ] [ MAX ] ; //dp[i][j][q]表示在(i,j)处且当前背包大小为q的情况下,i*j个物品最佳组合得到的最大价值 int main ( ) { int n , m , k , v1 , v2 ; //k为背包大小 while ( scanf_s ( "%d%d%d" , & n , & m , & k ) != EOF ) //保证循环输入测试用例 { memset ( dp , 0 , sizeof ( dp ) ) ; for ( int i = 1 ; i <= n ; i ++ ) { for ( int j = 1 ; j <= m ; j ++ )

[ZJOI2005]午餐 [动态规划]

亡梦爱人 提交于 2019-12-20 18:22:25
P2577 [ZJOI2005]午餐 每个人有排队和吃饭花费的时间 将人分为两队排队 求所有人最早吃完时间 可以想到吃饭吃的越久的人越早排队越优 所以从大到小排序 开始想到f[k][i][j]前k个人排队时1号窗口排队花费时间i 2号窗口花费时间j最早吃完时间 但会爆空间 继而 经过一系列思考 f[i][j]表示前i个人排队时1号窗口排队花费时间为j最早吃完时间 而2号窗口排队时间可以通过sum[i]-j得出 #include<bits/stdc++.h> using namespace std; #define Max(x,y) (x)>(y)?(x):(y) #define Min(x,y) (x)>(y)?(y):(x) #define ll long long #define rg register const int N=200+5,M=10000+5,inf=0x3f3f3f3f,P=99999997; int n,sum[N],f[N][N*N],ans=inf; template <class t>void rd(t &x){ x=0;int w=0;char ch=0; while(!isdigit(ch)) w|=ch=='-',ch=getchar(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar

ACM算法总结及刷题参考

谁说我不能喝 提交于 2019-12-20 11:48:08
参考: http://bbs.byr.cn/#!article/ACM_ICPC/11777 OJ上的一些水题(可用来练手和增加自信) (poj3299,poj2159,poj2739,poj1083,poj2262,poj1503,poj3006,poj2255,poj3094) 初期: 一.基本算法: (1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586) (3)递归和分治法. (4)递推. (5)构造法.(poj3295) (6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996) 二.图算法: (1)图的深度优先遍历和广度优先遍历. (2)最短路径算法(dijkstra,bellman-ford,floyd,heap+dijkstra) (poj1860,poj3259,poj1062,poj2253,poj1125,poj2240) (3)最小生成树算法(prim,kruskal) (poj1789,poj2485,poj1258,poj3026) (4)拓扑排序 (poj1094) (5)二分图的最大匹配 (匈牙利算法) (poj3041,poj3020) (6)最大流的增广路算法(KM算法). (poj1459,poj3436) 三.数据结构. (1)串 (poj1035