动态规划

动态规划

橙三吉。 提交于 2019-11-29 13:33:39
题目:求解一个数组中不相邻元素的最大和 分析:首先从最后一个元素开始分析,如果选最后一个元素的话,就不能选倒数第二个元素,这时要考虑OPT(n)=max(OPT(n-2)+arr[n], OPT(n-1)),这个就是递归的公式,然后设计递归出口,当n=1时 上面的式子不成立,OPT(1)=max(arr[0],arr[1]),当n=2时,OPT[2] = max(arr[0],arr[1]) 递归代码 arr = [1,2,4,1,7,8,3] def rec_opt(arr,i): if i==0: return arr[0] elif i==1: return max(arr[0],arr[1]) else: A = rec_opt(arr,i-2)+arr[i] B = rec_opt(arr,i-1) return max(A,B) res = rec_opt(arr,6) print(res) 动态规划解法 设计一个数组,从头到尾计算OPT,并保存在数组内 import numpy as np def dp_opt(arr): opt = np.zeros(len(arr)) opt[0] = arr[0] opt[1] = max(arr[0],arr[1]) for i in range(2,len(arr)): A = opt[i-2]+arr[i] B = opt

递归和动态规划

假如想象 提交于 2019-11-29 13:02:04
递归算法就是通过解决同一问题的一个或多个更小的实例来最终解决一个大问题的算法。为了在C语言中实现递归算法,常常使用递归函数,也就是说能调用自身的函数。递归程序的基本特征:它调用自身(参数的值更小),具有终止条件,可以直接计算其结果。 在使用递归程序时,我们需要考虑编程环境必须能够保持一个其大小与递归深度成正比例的下推栈。对于大型问题,这个栈需要的空间可能妨碍我们使用递归的方法。 一个递归模型为分治法,最本质的特征就是:把一个问题分解成独立的子问题。如果子问题并不独立,问题就会复杂的多,主要原因是即使是这种最简单算法的直接递归实现,也可能需要难以想象的时间,使用动态规划技术就可以避免这个缺陷。 例如,斐波那契数列的递归实现如下: int F(int i) { if(i < 1) return 0; if(i == 1) return 1; return F(i-1) + F(i - 2); } 千万不要使用这样的程序,因为它的效率极低,需要指数级时间。相比之下,如果首先计算前N个斐波那契数,并把它们存储在一个数组中,就可以使用线性时间(与N成正比)计算F。 F[0] = 0;F[1] = 1; for(i = 2; i <= N; i++) F[i] = F[i-1] + F[i-2]; 这个技术给了我们一个获取任何递归关系数值解的快速方法,在斐波那契数的例子中,我们甚至可以舍弃数组

杭电1003--动态规划

雨燕双飞 提交于 2019-11-29 11:57:33
思路:用数组a[]记录序列中的数,对于a[i]只有两种可能 1.为一个序列的首2.为一个序列的尾。 用数组b[i]记录以第i个数结尾的序列的最大和,则 b[i]=max(b[i-1]+a[i],a[i]) b[i-1]+a[i]和a[i]分别对应a[i]的两种情况。 #include<bits/stdc++.h> #define maxn 100014 int a[maxn]; int b[maxn]; using namespace std; int main(){ int t; int k=1; cin>>t; while(t--){ int sum=0; int n,begin,end; int max0=-1001;//表示最小值 cin>>n; memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); for(int i=1;i<=n;i++){ cin>>a[i];//读入数据 b[i]=max(b[i-1]+a[i],a[i]); if(max0<b[i])//找到结束的位置 { max0=b[i]; end=i; } } for(int i=end;i>=1;i--){//从结束的位置开始把每个数加上,然后相等的时候找到起始位置 sum+=a[i]; if(sum==max0) begin=i; } cout<<"Case "<<k

leetcode中完全背包问题集合

谁都会走 提交于 2019-11-29 11:18:38
这两天在刷leetcode的动态规划的题目时,发现很多动态规划的题目怎么想都很难出递推公式,而看答案往往都感觉是精巧设计的,但是遇到类似的题目又不知从何下手,看了一天的博客和其他资料,发现这种类型的题目都是一类经典问题的变种:背包问题 背包问题主要有3种基本类型:01背包,完全背包,多重背包问题。 这里列出几个写的比较好的博客:大家可先行补充下基本知识(主要是leetcode中的题目不会让人立刻联想到是背包问题,所以看基本概念的目的是深入熟悉和记住递推公式的模板,方便套用)。 背包问题九讲 动态规划解决01背包问题 本文是总结leetcode中的背包变形问题的集锦,所以会不断更新,首先来看困扰我的leetcode中的二维递推公式的都长什么样: for (int i = 1; i <= m; i++) { for (int j = 0; j < n; j++) { dp[i] = min(dp[i], dp[i - coins[j]] + 1); } } 注意看红字所示,递推公式中会减去外层循环中的某个值,而不是我们常见的如下模板: for (int i = 1; i <= m; i++) { for (int j = 0; j < n; j++) { dp[i] = min( dp[i-1]+A[i] , dp[i]); } } 这种反减的模板套路就和背包问题很像

Poj题不完全分类

元气小坏坏 提交于 2019-11-29 10:49:06
初期: 一.基本算法: (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,poj3080,poj1936) (2)排序(快排、归并排(与逆序数有关)、堆排) (poj2388,poj2299) (3)简单并查集的应用. (4)哈希表和二分查找等高效查找法(数的Hash,串的Hash) (poj3349,poj3274,POJ2151,poj1840

Comb CodeForces - 46E (动态规划)

孤者浪人 提交于 2019-11-29 09:59:46
题面 Having endured all the hardships, Lara Croft finally found herself in a room with treasures. To her surprise she didn't find golden mountains there. Lara looked around and noticed on the floor a painted table n × m panels in size with integers written on the panels. 题意 在一个 \(n * m\) 的矩阵中,第 \(i\) 取前 \(c_i\) 个元素,要求 \(c1 > c2 < c3 > c4 < ...\) 求最后取到的元素和的最大值. 思路 \(dp[i][j]\) 表示第 \(i\) 行取 \(j\) 个元素的最大值. 在奇数行和偶数行按不同的顺序更新就行了. #include<iostream> #include<algorithm> #include<vector> #include<stack> #include<queue> #include<map> #include<set> #include<cstdio> #include<cstring> #include<cmath>

Leetcode之动态规划(DP)专题-647. 回文子串(Palindromic Substrings)

老子叫甜甜 提交于 2019-11-29 08:36:57
Leetcode之动态规划(DP)专题-647. 回文子串(Palindromic Substrings) 给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。 具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被计为是不同的子串。 示例 1: 输入: "abc" 输出: 3 解释: 三个回文子串: "a", "b", "c". 示例 2: 输入: "aaa" 输出: 6 说明: 6个回文子串: "a", "a", "a", "aa", "aa", "aaa". 注意: 输入的字符串长度不会超过1000。 dp: 定义: dp[i][j]表示在从i开始到j结束这段字符串里,如果是回文串,则dp[i][j]=1,不是则dp[i][j]=0; 状态转移方程: if((s.charAt(i)==s.charAt(j)) && ((j-i<=2) || dp[i+1][j-1]==1)){   dp[i][j] = 1; } 举例解释: "aba" i=2 j=2    "a" 长度为1,是回文字符串。 i=1 j=1    "b" 长度为1,是回文字符串 i=1 j=2    "ab" 长度为2,但左不等于右,不是 i=0 j=0    "a" 长度为1,是回文字符串 i=0 j=1    "ab" 长度为2,且左不等于右,不是 i=0 j=2    "aba"

Leetcode之动态规划(DP)专题-474. 一和零(Ones and Zeroes)

微笑、不失礼 提交于 2019-11-29 08:34:20
Leetcode之动态规划(DP)专题-474. 一和零(Ones and Zeroes) 在计算机界中,我们总是追求用有限的资源获取最大的收益。 现在,假设你分别支配着 m 个 0 和 n 个 1 。另外,还有一个仅包含 0 和 1 字符串的数组。 你的任务是使用给定的 m 个 0 和 n 个 1 ,找到能拼出存在于数组中的字符串的最大数量。每个 0 和 1 至多被使用一次。 注意: 给定 0 和 1 的数量都不会超过 100 。 给定字符串数组的长度不会超过 600 。 示例 1: 输入: Array = {"10", "0001", "111001", "1", "0"}, m = 5, n = 3 输出: 4 解释: 总共 4 个字符串可以通过 5 个 0 和 3 个 1 拼出,即 "10","0001","1","0" 。 示例 2: 输入: Array = {"10", "0", "1"}, m = 1, n = 1 输出: 2 解释: 你可以拼出 "10",但之后就没有剩余数字了。更好的选择是拼出 "0" 和 "1" 。 dp[i][j]表示有 i个0 和 j个1时的最大数量。状态转移方程:dp[i][j] = Max(dp[i][j],dp[i-零的数量][j-一的数量]+1); class Solution { public int findMaxForm

Leetcode之动态规划(DP)专题-486. 预测赢家(Predict the Winner)

*爱你&永不变心* 提交于 2019-11-29 08:32:49
Leetcode之动态规划(DP)专题-486. 预测赢家(Predict the Winner) 给定一个表示分数的非负整数数组。 玩家1从数组任意一端拿取一个分数,随后玩家2继续从剩余数组任意一端拿取分数,然后玩家1拿,……。每次一个玩家只能拿取一个分数,分数被拿取之后不再可取。直到没有剩余分数可取时游戏结束。最终获得分数总和最多的玩家获胜。 给定一个表示分数的数组,预测玩家1是否会成为赢家。你可以假设每个玩家的玩法都会使他的分数最大化。 示例 1: 输入: [1, 5, 2] 输出: False 解释: 一开始,玩家1可以从1和2中进行选择。 如果他选择2(或者1),那么玩家2可以从1(或者2)和5中进行选择。如果玩家2选择了5,那么玩家1则只剩下1(或者2)可选。 所以,玩家1的最终分数为 1 + 2 = 3,而玩家2为 5。 因此,玩家1永远不会成为赢家,返回 False。 示例 2: 输入: [1, 5, 233, 7] 输出: True 解释: 玩家1一开始选择1。然后玩家2必须从5和7中进行选择。无论玩家2选择了哪个,玩家1都可以选择233。 最终,玩家1(234分)比玩家2(12分)获得更多的分数,所以返回 True,表示玩家1可以成为赢家。 注意: 1 <= 给定的数组长度 <= 20. 数组里所有分数都为非负数且不会大于10000000。

Leetcode之动态规划(DP)专题-264. 丑数 II(Ugly Number II)

非 Y 不嫁゛ 提交于 2019-11-29 08:31:32
Leetcode之动态规划(DP)专题-264. 丑数 II(Ugly Number II) 编写一个程序,找出第 n 个丑数。 丑数就是只包含质因数 2, 3, 5 的正整数。 示例: 输入: n = 10 输出: 12 解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。 说明: 1 是丑数。 n 不超过1690。 dp含义: dp[i]表示第i-1个丑数。 class Solution { public int nthUglyNumber(int n) { int[] dp = new int[n + 1]; dp[0] = 1; int i2 = 0; int i3 = 0; int i5 = 0; for (int i = 1; i < n + 1; i++) { dp[i] = Math.min(Math.min(dp[i2] * 2, dp[i3] * 3), dp[i5] * 5); if (dp[i] == dp[i2] * 2) { i2++; } if (dp[i] == dp[i3] * 3) { i3++; } if (dp[i] == dp[i5] * 5) { i5++; } } return dp[n - 1]; } } 来源: https://www.cnblogs.com/qinyuguan/p