动态规划

动态规划遍历顺序问题

北城余情 提交于 2019-12-02 10:37:19
首先0-1背包问题 f[i][j]=max( f [ i-1 ] [ j ],f[ i-1 ][ j - t[ i ] ] + v [ i ] ) 压缩至一维以后变成 f[i][j]=max( f[ j ],f[ j - t[ i ] ] + v [ i ] ) 相当于把第一维省略,后面计算的值不断覆盖前面的 如果从前向后遍历的话,假设f[j - t [i] ]的值已近被更新(加上了v[i]),在计算f[ i ][ j ]的时候,又会被更新,就相当于把一种东西加了两次,所以与题意一种物品只能加一次不符合,故要从后往前遍历 完全背包问题 f[i][j]=max( f [ i-1 ] [ j ],f[ i ][ j - n t[ i ] ] +n v [ i ] ) 压缩至一维以后 f[i][j]=max( f[ j ],f[ j - n t[ i ] ] +n v [ i ] ) 注意到第一个i - 1和第二个 i 都被压缩了,但这两个含义不同i - 1的含义是更新之前的,而i 的含义是更新之后的,所以就像上面的一样,因为现在一种物品可以加无限次,所以就从前向后遍历 来源: https://blog.csdn.net/qq_43261254/article/details/102752772

【动态规划】数字金字塔

廉价感情. 提交于 2019-12-02 06:55:39
数字金字塔 Description 考虑在下面被显示的数字金字塔。 写一个程序来计算从最高点开始在底部任意处结束的路径经过数字的和的最大。 每一步可以走到左下方的点也可以到达右下方的点。 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 在上面的样例中,从7 到 3 到 8 到 7 到 5 的路径产生了最大和:30 Input 第一个行包含 R(1<= R<=1000) ,表示行的数目。 后面每行为这个数字金字塔特定行包含的整数。 所有的被供应的整数是非负的且不大于100。 Output 单独的一行包含那个可能得到的最大的和。 Sample Input 5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 Sample Output 30 解题思路: 这道题用递推的方法来做,应为本行的结果只和下一层有关系,所以可以用一维数组倒着递推算出结果。 状态转移方程: st[j]=max(st[j],st[j+1])+a[i][j]; # include <cstdio> # include <iostream> using namespace std ; int st [ 1001 ] , a [ 1001 ] [ 1001 ] , n ; int main ( ) { scanf ( "%d" , & n ) ; for ( int i = 1 ; i <= n ;

DP:从零开始的动态规划

99封情书 提交于 2019-12-02 06:28:46
从现在开始学习dp 来一个入门的 T1:数字三角形 时间限制: 1000 ms 内存限制: 65536 KB 【题目描述】 观察下面的数字金字塔。写一个程序查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以从当前点走到左下方的点也可以到达右下方的点。 在上面的样例中,从13到8到26到15到24的路径产生了最大的和86。 【输入】 第一个行包含R(1≤ R≤1000),表示行的数目。 后面每行为这个数字金字塔特定行包含的整数。 所有的被供应的整数是非负的且不大于100。 【输出】 单独的一行,包含那个可能得到的最大的和。 【输入样例】 5 13 11 8 12 7 26 6 14 15 8 12 7 13 24 11 【输出样例】 86 #include<bits/stdc++.h> #define re register #define ll long long using namespace std; template <typename T> inline void read(T &x) { int f=1;x=0;char c=getchar(); for(;c>'9'||c<'0';c=getchar()) if(c=='-') f=-1; for(;c>='0'&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);

luogu 动态规划口胡合集

≡放荡痞女 提交于 2019-12-02 05:46:14
P1831 杠杆数 是否说出正解: × 显然是个数位DP,但是感觉无从下手,事实上可以做18次数位dp,每次枚举支点,就可以算出每个数的力矩,取出力矩为0的作为贡献即可 #include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <bitset> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define

动态规划小练

百般思念 提交于 2019-12-02 03:29:27
终于意识到动规的水平差得一批了。这边开个小专题练一下。 题目列表是学长 frank_c1 的博客。这样一来可以保证质量,二来也有自己能看懂的题解。 事实上很多题意也是贺的 这里还是挂个链接吧: orz (刷新以获取数学公式) [APIO 2014] Beads and wires 题意 在达芬奇时代,有一个流行的儿童游戏称为连珠线。当然,这个游戏是关于珠子和线的。线是红色或蓝色的,珠子被编号为 $ 1 $ 到 $ n $ 。这个游戏从一个珠子开始,每次会用如下方式添加一个新的珠子: $ Append(w, v) $ :一个新的珠子 $ w $ 和一个已经添加的珠子 $ w $ 用红线连接起来。 $ Insert(w, u, v) $ :一个新的珠子 $ w $ 插入到用红线连起来的两个珠子 $ u $ , $ v $ 之间。具体过程是删去 $ u $ , $ v $ 之间红线,分别用蓝线连接 $ u $ , $ w $ 和 $ w $ , $ v $ 。 每条线都有一个长度。游戏结束后,你的最终得分为蓝线长度之和。 给你连珠线游戏结束后的游戏局面,只告诉了你珠子和链的连接方式以及每条线的长度,没有告诉你每条线分别是什么颜色。 你需要写一个程序来找出最大可能得分。即,在所有以给出的最终局面结束的连珠线游戏中找出那个得分最大的,然后输出最大可能得分。 数据范围: $ 1≤n

动态规划总结

a 夏天 提交于 2019-12-02 02:34:27
---恢复内容开始--- 动态规划来源于分治法,本质是为了节省递归栈所消耗的时间/空间,同时把相同的子问题的解记录下来,防止系统做重复工作,浪费时间。 一般用动态规划做题时候,要从分治法开始,进一步考虑是否存在相同的子问题解且解是否重复,如果有可以采用动态规划求解【当然递归方程还是要写的】。 动态规划的递归方程和分治法略有不同,动态规划的递归一般都用二维数组储存数据【当然也有用一维数组甚至一个变量的,不过都是二维数组的简化版】,首先我们要弄清楚m[i][j]的几何意义,然后根据题目要求写出m[i][j]=...【一般都是和m其他元素挂钩的】,这就是动态规划的递归方程。 一般写递归方程分为以下几种情况 1.确定规划起点终点,规划方向确定 例题: 7-1 数字三角形 (30 分) 给定一个由 n行数字组成的数字三角形如下图所示。试设计一个算法,计算出从三角形 的顶至底的一条路径(每一步可沿左斜线向下或右斜线向下),使该路径经过的数字总和最大。 输入格式: 输入有n+1行: 第 1 行是数字三角形的行数 n,1<=n<=100。 接下来 n行是数字三角形各行中的数字。所有数字在0..99 之间。 输出格式: 输出最大路径的值。 输入样例: 在这里给出一组输入。例如: 5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 输出样例: 在这里给出相应的输出。例如: 30

[C++] LeetCode 132. 分割回文串 II

天涯浪子 提交于 2019-12-02 02:32:08
题目 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。 返回 s 符合要求的的最少分割次数。 例如,给出 s = "aab" , 返回 1 因为进行一次分割可以将字符串 s 分割成 ["aa","b"] 这样两个回文子串。 题解 这题有两种解法,但是都是采用动态规划。数组 nums[i] 表示前 i 字符串最小的分割次数,那么在遍历过程中需要知道 j 至 i 的字符串是否为回文串。 方法一 先用动态规划,用一个二维数组 flag[i][j] 表示字符串第 j 个到第 i 个是否为回文串。然后再用一次动态规划,得出最小分割次数。但是时间复杂度较高。 代码如下: class Solution { public : int minCut ( string s ) { if ( s . size ( ) == 0 ) return 0 ; int len = s . size ( ) ; vector < vector < bool >> flag ( len , vector < bool > ( len , false ) ) ; for ( int k = 0 ; k < len ; k ++ ) { for ( int i = 0 , j = k ; j < len ; i ++ , j ++ ) { if ( i == j ) flag [ i ] [ j ]

LeetCode132——分割回文串II

允我心安 提交于 2019-12-02 02:30:31
我的LeetCode代码仓: https://github.com/617076674/LeetCode 原题链接: https://leetcode-cn.com/problems/palindrome-partitioning-ii/description/ 题目描述: 知识点:动态规划 思路:动态规划 首先是对回文串的判断,不像 LeetCode131——分割回文串 中的做法,对一个字符串s用指向首字符和末字符的双指针分别向后和向前遍历字符串s中的字符来判断s是否是回文串。 本题对回文串的判别方法使用动态规划的思路。对于字符串s,如果其首字符和末字符不相同,显然其不是一个回文串。如果其首字符和末字符相同,那么我们去判断字符串s出去首字符和末字符的子串是否是回文串。 状态定义 :judge(i, j) -------- 字符串s中[i, j]范围内的子串是否是回文串 状态转移 : (1)如果s.charAt(i) != s.charAt(j),judge(i)(j) = false。 (2)如果s.charAt(i) == s.charAt(j), a:如果此时j - i <= 1,即[i, j]范围内的字符个数小于等于2个,judge(i)(j) = true。 b:否则,judge(i)(j) = judge(i + 1)(j - 1)。 很显然的一点是

算法第3章小结

北慕城南 提交于 2019-12-02 00:44:39
动态规划    基本要素: (1)最优子结构性质    (2)重叠子问题性质    步  骤: (1)找出最优解的性质,并刻画其结构特征        (2)递归地定义最优值        (3)以自底向上的方式计算最优值        (4)根据计算最优值时的信息构造最优解    自底向上的填表方法 :(1)表的维数             (2)填表范围             (3)填表顺序    【例1】矩阵连乘问题 void MatixChain(int *p, int n, int **m, int **s){  for(int i = 1; i <= n; i++)    m[i][i] = 0;  for(int r = 2; r <= n; r++){    for(int i = 1; i <= n-r+1; i++){      int j = i+r-1;      m[i][j] = m[i+1][j] + p[i-1] * p[i] * p[j];      s[i][j] = i;      for(int k = i + 1; k < j; k++){        int t = m[i][k] + m[k+1][j] + p[i-1] * p[i] * p[j];        if(t < m[i][j]){          m[i][j]

动态规划LeetCode53最大子序和

南楼画角 提交于 2019-12-01 23:48:38
最大子序和(最大子段和)是非常经典的动态规划题目,其变形题目也很多。 LeetCode53最大子序和 题目描述: 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。 题解: 1 class Solution { 2 public int maxSubArray( int [] nums) { 3 int [] dp= new int [nums.length]; 4 dp[0]=nums[0 ]; 5 int max=dp[0 ]; 6 for ( int i=1;i<nums.length;i++ ) { 7 dp[i]=Math.max(nums[i],dp[i-1]+ nums[i]); 8 if (dp[i]> max) { 9 max= dp[i]; 10 } 11 } 12 return max; 13 } 14 } 下一道经典动态规划题目LeetCode322零钱兑换 欢迎评论!!共同进步!! 转载于:https://www.cnblogs.com/hengzhezou/p/11042789.html 来源: CSDN 作者: weixin_30361641 链接: https: