动态规划

动态规划-1620. 收集硬币

感情迁移 提交于 2020-04-08 08:47:49
2020-04-08 07:45:18 问题描述: 给定一个 n * m 个的矩阵,矩阵的每个位置有一定数量的硬币,你从 (0,0) 位置出发,每次只能 往右 或者 往下 走,当他经过某个格子的时候,可以得到这个格子上的所有硬币,当它走到第 (n-1,M-1) 位置时游戏结束,在游戏开始前,你有 ķ 次机会,可以交换某两个格子中的硬币数量中,k次机会不一定要使用完,求从(0,0)走到第(n-1,M-1)所能得到的最大的硬币数量。 样例 输入: matrix = [[9,9,9,0,0],[0,0,9,0,0],[0,0,0,0,0],[0,0,9,0,0],[9,0,9,9,9]] k = 1 输出:81 注意事项 2≤n,m≤50 0<=k<=20 0<=matrix[I][j]<=1000000 问题求解: int nums[55]; int dp[55][55][25][25]; int collectingCoins(vector<vector<int>> &matrix, int k) { // Write your code here int n = matrix.size(); int m = matrix[0].size(); memset(dp, -0x3f,sizeof(dp)); dp[0][0][0][0] = matrix[0][0], dp[0][0]

典型的动态规划题目总结(斐波那契数列相关)

血红的双手。 提交于 2020-04-08 03:34:13
1.常规跳台阶 一只青蛙一次 可以跳上1级台阶,也可以跳上2级。 求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。 大体思路: 第 i 个楼梯可以从第 i-1 和 i-2 个楼梯再走一步到达,即走到第 i 个楼梯的方法数为走到第 i-1 和第 i-2 个楼梯的方法数之和。所以可以推导出递推公式为: dp[i]=dp[i-1]+dp[i-2] 考虑到 dp[i] 只与 dp[i - 1] 和 dp[i - 2] 有关,因此可以只用两个变量来存储 dp[i - 1] 和 dp[i - 2],使得原来的 O(N) 空间复杂度优化为 O(1) 复杂度。具体非递归代码如下: 2.变态跳台阶 一只青蛙一次 可以跳上1级台阶,也可以跳上2级……它也可以跳上n级 。求该青蛙跳上一个n级的台阶总共有多少种跳法。 大致思路: (1)每一个高度的台阶都可以一步完成,所以每一个位置都有一种基本解 dp[i]=1 (2)除了基本解之外,每一个高度的完成解还受到且仅受到前一个相邻高度dp[i-1]的影响。 (3)因此,每一个高度的最终解都是前一个数的解()+本身的基本解。即, dp[i]=1+dp[i-1]; 3.抢劫一排房子 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是 相邻的房屋装有相互连通的防盗系统

分蛋糕(动态规划)

橙三吉。 提交于 2020-04-07 19:49:57
描述 有一块矩形大蛋糕,长和宽分别是整数 w 、 h 。现要将其切成 m 块小蛋糕,每个小蛋糕都必须是矩形、且长和宽均为整数。切蛋糕时,每次切一块蛋糕,将其分成两个矩形蛋糕。请计算:最后得到的 m 块小蛋糕中,最大的那块蛋糕的面积下限。 假设 w = 4, h = 4, m = 4,则下面的切法可使得其中最大蛋糕块的面积最小。 假设 w = 4, h = 4, m = 3,则下面的切法会使得其中最大蛋糕块的面积最小: 输入 共有多行,每行表示一个测试案例。每行是三个用空格分开的整数w, h, m ,其中1 ≤ w, h, m ≤ 20 , m ≤ wh. 当 w = h = m = 0 时不需要处理,表示输入结束。 输出 每个测试案例的结果占一行,输出一个整数,表示最大蛋糕块的面积下限。 样例输入 4 4 4 4 4 3 0 0 0 样例输出 4 6 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 5 using namespace std; 6 7 const int INF = 0x3f3f3f3f; 8 int Minmax[22][22][22]; // Min[i][j][k]表示 i*j的蛋糕分成为k+1块(切k刀)最大的那块蛋糕的最小面积 9 10 int main() { 11 int w,

【动态规划】Luogu P5774 病毒感染(待补全)

倾然丶 夕夏残阳落幕 提交于 2020-04-04 18:38:22
题目大意 题目链接 有 n ​ 个村庄,每个村庄 每天会因传染病去世 a i 个 人(除非你治愈这个村庄)。 从1号村庄出发,每天可以选择向相邻的村庄进发或者治愈所在的村庄。 如果在这个过程中之前有未治愈的村庄,同时你往回走了一步,那么你需要把之前未治愈的村庄全部治愈后才能接着自由行动。 求所有村庄都被治愈时最少的死亡人数。 数据范围 n≤3000,a i ≤10 9 样例输入 6 40 200 1 300 2 10 样例输出 1950 样例解释 见链接 ヾ(。 ̄□ ̄)ツ゜゜゜ 思路 建议改成:江 苏 题 N B 暴力枚举n 3 显然不怎么优秀,所以我们选择动态规划。 转移方程:   dp [j] [i+j]=dp [j+1] [i+j]+min((sum [i+j]-sum [j])* 2,a [j]*i* 3+sum [i+j]-sum [j]);   dp2 [i]=min(dp2 [i],dp2 [j]+dp [j+1] [i]+( 4*i- 4*j- 2)*(sum [n]-sum [i])); 代码 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=3000+10; 5 ll n,dp[maxn][maxn],dp2[maxn],sum

动态规划(股票交易)---只能进行两次的股票交易

人盡茶涼 提交于 2020-04-02 12:12:51
只能进行两次的股票交易 123. Best Time to Buy and Sell Stock III (Hard) 题目描述:   一共只能进行两次股票交易,求能够取得的最大利润。 思路分析:   这道题是Best Time to Buy and Sell Stock的扩展,现在我们最多可以进行两次交易。我们仍然使用动态规划来完成,事实上可以解决非常通用的情况,也就是最多进行k次交易的情况。   这里我们先解释最多可以进行k次交易的算法,然后最多进行两次我们只需要把k取成2即可。我们还是使用“局部最优和全局最优解法”。我们维护两种量,一个是当前到达第i天可以最多进行j次交易,最好的利润是多少(global [i] [j]),另一个是当前到达第i天,最多可进行j次交易,并且最后一次交易在当天卖出的最好的利润是多少(local [i] [j])。下面我们来看递推式,全局的比较简单,   global [i] [j]=max(local [i] [j],global [i-1] [j]),   也就是取当前局部最好的,和过往全局最好的中大的那个(因为最后一次交易如果包含当前天一定在局部最好的里面,否则一定在过往全局最优的里面)。对于局部变量的维护,递推式是 local [i] [j]=max(global [i-1] [j-1]+max(diff,0),local [i-1] [j]

1D1D动态规划优化初步

℡╲_俬逩灬. 提交于 2020-04-02 05:22:49
再学习一下动态规划的基本优化方法… 首先这篇文章应该大家都看过吧…没看过的自行百度 关于实现的思路文章里都给好了…这篇就主要给一点题目啥的 (P.S. 电脑重装了,如果博客发出来有一些奇怪的问题不要在意) 模型一,即决策单调性优化 ①玩具装箱 bzoj1010 题目自己看去 用dp[x]表示装前x个的最小费用,sum[x]表示C的前缀和。 可以发现dp[i]=min{dp[j]+(i-j+sum[i]-sum[j]-1-L)^2} (0<=j<i) 这样似乎还是不够美观,我们令p[i]=i+sum[i],g=L+1。 dp[i]=min{dp[j]+(p[i]-p[j]-g)^2} (0<=j<i) 美观了一点… 这样硬肛是O(n^2)的,感觉很不兹磁啊… 首先:四边形不等式 当函数w(i,j)满足w(a,c)+w(b,d)<=w(b,c)+w(a,d)且a<=b<c<=d时我们称w(i,j)满足四边形不等式。 假如我们用w(j,i)表示(p[i]-p[j]-g)^2,那么(打表)可以发现w是满足四边形不等式的。 什么?讲道理? w(a,c)+w(b,d)-w(b,c)-w(a,d)=2g(p[c]-p[a]+p[d]-p[b]-p[c]+p[b]-p[d]+p[a])+p[a]^2+p[c]^2+p[b]^2+p[d]^2-p[b]^2-p[c]^2-p[a]^2-p[d]^2

dfs,动态规划和记忆化搜索

安稳与你 提交于 2020-03-30 08:18:17
可以用dfs的题目可以想一下是否能用动态规划解决,可以省掉大量开栈和栈回收的开销; 如果不可以那想一下是否能用记忆化搜索,这样可以省掉大量重复子问题计算的开销; 关于区间DP,关于字符串或者是一段序列的问题多数是区间DP的问题;但是可能会涉及到如何定义相同子串的问题 ; 来源: https://www.cnblogs.com/mychen06/p/12596396.html

Leetcode:Palindrome Partitioning II

扶醉桌前 提交于 2020-03-30 07:18:57
Description: Given a string s , partition s such that every substring of the partition is a palindrome. Return the minimum cuts needed for a palindrome partitioning of s . For example, given s = "aab" , Return 1 since the palindrome partitioning ["aa","b"] could be produced using 1 cut. 分析:求字符串的最小切,简单来看 对每一个新字符,往前找到它组成的所有回文,保留最小值,遍历整个字符串,即可以得到最小切得结果。 这里往前找,会将字符串分成两部分,带当前字符的回文部分,和前面的字符串部分。这样就会带来大量的重复子问题,当然考虑是动态规划来做。 动态规划的递归式是: F(x) = min{F(j)+1} for all j,s.t string [j+1,x] is a palindrome. 这里还有一个技巧需要注意,因为此时我们就需要判断一个字符串是否是回文串,判断方法也应该用动态规划来做,否则会超时。 判断回文的动归 比较简单,递归式是 B[i][j] = (s[i]==s[j]) && B[i

Leetcode之动态规划(DP)专题-746. 使用最小花费爬楼梯(Min Cost Climbing Stairs)

心已入冬 提交于 2020-03-29 16:54:50
Leetcode之动态规划(DP)专题-746. 使用最小花费爬楼梯(Min Cost Climbing Stairs) 数组的每个索引做为一个阶梯,第 i 个阶梯对应着一个非负数的体力花费值 cost[i] (索引从0开始)。 每当你爬上一个阶梯你都要花费对应的体力花费值,然后你可以选择继续爬一个阶梯或者爬两个阶梯。 您需要找到达到楼层顶部的最低花费。在开始时,你可以选择从索引为 0 或 1 的元素作为初始阶梯。 示例 1: 输入: cost = [10, 15, 20] 输出: 15 解释: 最低花费是从cost[1]开始,然后走两步即可到阶梯顶,一共花费15。 示例 2: 输入: cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1] 输出: 6 解释: 最低花费方式是从cost[0]开始,逐个经过那些1,跳过cost[3],一共花费6。 注意: cost 的长度将会在 [2, 1000] 。 每一个 cost[i] 将会是一个Integer类型,范围为 [0, 999] 。 DP: dp[i]表示上到第i个楼梯的最小花费。 注意几个点: 1、楼顶的下标是 cost.length 2、一开始你所在的下标是-1或者-2(因为可以一次走一层,如果一次走一层你就在-1,如果一次走2层你就在-2) 为了优化这几点,我们把dp数组的length+3.