动态规划

动态规划习题(二)

左心房为你撑大大i 提交于 2020-02-08 19:10:36
leetcode 300. 最长上升子序列 O(N^2)解法,动态规划 func lengthOfLIS ( nums [ ] int ) int { n := len ( nums ) if n == 0 { return 0 } ret := 1 dp := make ( [ ] int , n ) dp [ 0 ] = 1 // dp[i]表示,包括i这个数的数组,最大 for i := 1 ; i < n ; i ++ { // 初始值都为1 dp [ i ] = 1 for j := 0 ; j < i ; j ++ { // 如果当前数字大于那个位置的数字,那么显然算上当前数字,序列会加1 // 比那个位置小或者等于那个位置的情况,在之前或者之后的j得到处理(即和每个j都比较了) // dp[i] 取之前的所有dp[j]中的最大值加1 if nums [ i ] > nums [ j ] { dp [ i ] = max ( dp [ i ] , dp [ j ] + 1 ) } } ret = max ( ret , dp [ i ] ) } return ret } O(NlogN),第二层循环用二分法替换 func lengthOfLIS ( nums [ ] int ) int { n := len ( nums ) if n == 0 { return 0 }

强化学习(2) 动态规划(Dymatic Progressing)

核能气质少年 提交于 2020-02-08 16:09:18
1. 1 同步价值迭代 动态规划来解决强化学习的规划问题。 在已经了解了状态、行为空间、转移概率矩阵、奖励等信息的基础上,判断一个策略的价值函数。或者判断策略的优劣寻找最优的策略。 一般强化学习是不知道上述的一些动力学环境,而且复杂的问题无法通过动态规划解决。 动态规划思想是把复杂问题变成求解子问题,最终再得到整个问题。子问题的结果一般需要保存以备后用。如果某个子问题重复出现,就可以重复使用结果。 马尔科夫决策过程最终用贝尔曼方程描述,贝尔曼方程是递归定义的。可以使用动态规划求解。 1.1. 概念: 预测prediction :已知MDP和一个策略 π \pi π ,或者MRP,求解该策略的 价值函数 v π v_\pi v π ​ 。 控制control :已知MDP,求最优的价值函数 v ∗ v_* v ∗ ​ 和 π ∗ \pi_* π ∗ ​ ,为了寻找最优策略 1.2. 预测 1.2.1. 策略评估 Policy evaluation 给定策略,求这个策略下状态价值函数。 方法:同步迭代联合动态规划的算法 任意 的 状态价值函数 开始,按照给定 策略 ,通过 贝尔曼方程 、 状态转移概率、奖励 ,同步迭代更新 状态价值函数 ,到 收敛 为止。就可以得到这个策略的最优状态价值函数。 重点:在一个迭代周期如何更新 每一个状态 的价值 这个算法一定可以收敛形成一个稳定的价值函数

动态规划之自由组合问题

*爱你&永不变心* 提交于 2020-02-08 09:12:37
题目特征: 1.有一定的钱,去买一些东西,求最多有多少买种东西的方案? 2.如果一种物品最多能买一次,则是01背包变形类型 3.如果一个物品能多次购买,则是完全背包变形类型 4.每一种买东西的方案必须要把钱刚好花完。 相关例题: 1. 神奇的口袋 2. 买书 第一道题里“钱”是固定的,输入“东西的价格”;第二道题里“东西的价格”是固定的,输入“钱”。虽然输入的东西不一样,但是这一点是类似的,因为遍历时每一种情况都会遍历。 这题不同的地方是前者每个物品最多用一次,后者一种书可以多次购买,一个是01背包的变形,一个是完全背包的变形。 第一题代码: //神奇的口袋 #include<iostream> using namespace std; int main() { int n,i,j,a[201],dp[401]={0}; cin>>n; dp[0]=1; for(i=1;i<=n;i++) cin>>a[i]; for(i=1;i<=n;i++) { for(j=400;j>=a[i];j--) { dp[j]+=dp[j-a[i]]; dp[j]%=10000; } } cout<<dp[400]<<endl; return 0; } 第二题代码: //买书 #include <iostream> using namespace std; int w[4] = {1,2,3,4}

动态规划-01背包-Tallest Billboard

白昼怎懂夜的黑 提交于 2020-02-07 19:20:09
2020-02-07 17:46:32 问题描述: 问题求解: 解法一:BF 看问题规模看似可以直接暴力解决。 如果直接去解肯定是会超时的,因为每次将原空间划分成A区域,B区域和剩余区域的时间复杂度为O(3 ^ n)。 但是我们可以将问题进行一下转化,之前有个问题是能否将一个数组中的数划分成两个和相等的子区域那个题目是可以使用dp完成求解的,时间复杂度是O(nsum)。 因此我们可以去构造出所有的挑选可能,并对每个可能产生解的可能去过一遍dp就能完成本题。 但是,本解法并不是最优解。 int ret = 0; int[] nums; List<Integer> res = new ArrayList<>(); public int tallestBillboard(int[] rods) { nums = rods; helper(0, 0); return ret; } private void helper(int start, int sum) { if (start >= nums.length) return; if (sum % 2 == 0 && check(res, sum / 2)) { ret = sum / 2; } helper(start + 1, sum); res.add(nums[start]); sum += nums[start]; if

dp-动态规划

我与影子孤独终老i 提交于 2020-02-07 16:53:40
P1002 过河卒 这个题要画出图,标出每个点的种数,就容易找到状态转移方程 # include <bits/stdc++.h> using namespace std ; long long s [ 30 ] [ 30 ] , dp [ 30 ] [ 30 ] ; int dir [ 9 ] [ 2 ] = { { 0 , 0 } , { 1 , - 2 } , { 2 , - 1 } , { 2 , 1 } , { 1 , 2 } , { - 1 , 2 } , { - 2 , 1 } , { - 2 , - 1 } , { - 1 , - 2 } } ; int main ( ) { int ax , ay , mx , my ; cin >> ax >> ay >> mx >> my ; ax ++ ; ay ++ ; mx ++ ; my ++ ; dp [ 1 ] [ 1 ] ++ ; for ( int i = 0 ; i < 9 ; i ++ ) //标记9个位置 { s [ mx + dir [ i ] [ 0 ] ] [ my + dir [ i ] [ 1 ] ] = 1 ; } for ( int i = 1 ; i <= ax ; i ++ ) { for ( int j = 1 ; j <= ay ; j ++ ) { if ( s [ i ] [ j

牛客-H.施魔法(动态规划优化)

≡放荡痞女 提交于 2020-02-07 12:08:38
题意:牛可乐有n个元素(编号1...n),第i个元素的能量值为ai。牛可乐可以选择至少k个元素来释放一次魔法,魔法消耗的魔力是这些元素能量值的极差. 形式化地,若所用元素编号集合为S,则消耗的魔力为这个集合中的最大值减最小值。 牛可乐要求每个元素必须被使用恰好一次。牛可乐想知道他最少需要多少魔力才能用完所有元素,请你告诉他。 (链接)[ https://ac.nowcoder.com/acm/contest/3003/H ] 分析:贪心地思考,要使每次使用的魔力尽量小,必须是一段连续元素的区间,即要从小到大排序,然后,我们再使用动态规划进行转移,f[i]表示用掉前i个元素的最小花费,当我们计算第i个元素的时候, 它肯定是作为最小元素被减去的,然后最大元素是[1,i - k + 1]之间的,我们表示为j,同时还要加上f[j - 1],即用掉前j - 1个元素的最小值,那么状态转移方程就是f[i] = min(f[i], f[j - 1] + a[j] - a[i]) j∈[1, i - k + 1]。 //对于时间复杂度为0(n^2)的DP问题,我们可以采用一些优化,可以利用之前前缀的最小值进行优化,这样,代码的时间复杂度就会降到o(n)。 时间复杂度o(n^2) #include <iostream> #include <cstdio> #include <cstring>

动态规划之最长上升子序列

不羁的心 提交于 2020-02-07 06:19:25
给定一个无序的整数数组,找到其中最长上升子序列的长度。 示例: 输入: [10,9,2,5,3,7,101,18] 输出: 4 解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。 class Solution { public: int lengthOfLIS(vector<int>& nums) { if(nums.size() == 0) return 0; vector<int> dp(nums.size()+1,1); for(int i = 0; i < nums.size(); i++){ dp[i] = 1; for(int j = 0; j < i; j++){ if(nums[j] < nums[i]){ dp[i] = max(dp[i],dp[j]+1); } } } int max1 = 0; for(int i = 0;i < dp.size();i++){ max1 = max(dp[i],max1); } return max1; } }; 1)使用vector定义不定长集合 2)使用自带的max函数 3)dp[i]表示第i个数加入dp中的结果。当第i个数加入dp中时,我们依次遍历[0,i)的所有情况。一开始,我们总是假设dp[i] = 1;然后逐步增大j的值,当出现满足条件的情况,让他进行dp[i] 的值更新。 例如: [10,9

递归和动态规划裸题分析

那年仲夏 提交于 2020-02-07 04:02:12
递归和动态规划 裸题如下: https://www.luogu.com.cn/problem/P1060 递归 递归的思路如下: 思考递归边界。 确定最后应该向上层返回什么东西(例如这里向上层返回的就是权重值) 思考应该做什么重复的事(例如这里就是对是否买玩具做判断)。 思考应该向下面传递什么参数(例如这里就是(玩具数组索引,兜里剩的钱,当前已经攒了多少权重)) 完成以上思路很轻松就能写出以下代码。 import java.util.*; public class Main{ static int N,m; static int v[],w[]; static int _get(int deep,int money,int value){ if(deep==-1){ return value; } if(money<v[deep]){ return _get(deep-1, money, value); } int l = _get(deep-1, money, value); int r = _get(deep-1, money-v[deep], value+w[deep]); return r>l?r:l; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); m = sc

PAT 甲级 1040 Longest Symmetric String (25分)

那年仲夏 提交于 2020-02-07 01:21:59
Given a string, you are supposed to output the length of the longest symmetric sub-string. For example, given Is PAT&TAP symmetric? , the longest symmetric sub-string is s PAT&TAP s , hence you must output 11 . Input Specification: Each input file contains one test case which gives a non-empty string of length no more than 1000. Output Specification: For each test case, simply print the maximum length in a line. Sample Input: Is PAT&TAP symmetric? Sample Output: 11 最长回文子序列问题,用动态规划的方法去解决。按我目前的理解,与递归不同,动态规划中使用的递推是一种自底向上的方法,其含义便是把问题分割为最小子问题,用子问题的值去解决母问题。递归则是一种自顶向下的方法,在外层利用函数和方法将问题“递” 入内层,再利用边界将其

动态规划(dynamic programing)

爱⌒轻易说出口 提交于 2020-02-05 21:26:47
关键点 递推!(递归+记忆化) 状态定义:opt[n],重中之重! 状态转移方程:opt[n] = bestOf(opt[n-1], opt[n-2], ...) 最优子结构 比较 回溯(递归)- 重复计算,通常找不到最优子结构。 贪心 - 永远局部最优,局部最优不一定是全局最优。 动态规划 - 记录局部最优子机构(避免重复计算,再通过状态转移方程再递推下一个),集上述两者优点。 题目 leetcode 120. 三角形最小路径和 func minimumTotal ( triangle [ ] [ ] int ) int { n := len ( triangle ) mini := triangle [ n - 1 ] // 从下往上进行变例 for i := n - 2 ; i >= 0 ; i -- { for j := 0 ; j < len ( triangle [ i ] ) ; j ++ { // mini[j]使用一次,所以可以直接修改 mini [ j ] = triangle [ i ] [ j ] + min ( mini [ j ] , mini [ j + 1 ] ) } } return mini [ 0 ] } 来源: CSDN 作者: KeyboardMan6 链接: https://blog.csdn.net/weixin_40108561