动态规划

动态规划训练之七

心已入冬 提交于 2019-11-30 20:56:13
状压模板题,不多述,复习一下而已 code: #include<iostream> #include<stdio.h> #include<string.h> #include<math.h> using namespace std; const int maxn=20; int map[maxn][maxn],num,n,ans,nums; int f[maxn][1<<18]; void dp(){ memset(f,0x3f,sizeof(f)); for(int i=1;i<=n;i++)f[i][1<<(i-1)]=map[0][i]; nums=(1<<n)-1; for(int i=0;i<=nums;i++)//枚举所有可能的状态; for(int j=1;j<=n;j++) if(i&(1<<(j-1))) //枚举当前状态下到了第j个结点 for(int k=1;k<=n;k++) {//从j之k,找出到k的最优值。 if((i&(1<<(k-1)))==0) //如果第k结点还到,那么到达k,并更新其值。 f[k][i|(1<<(k-1))] =min(f[k][i|(1<<(k-1))],f[j][i]+map[j][k]); } ans=1<<20; for(int i=1;i<=n;i++) ans=min(ans,f[i][nums]+map[i][0]

算法分析之动态规划

早过忘川 提交于 2019-11-30 20:42:54
  动态规划(Dynamic Programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法。20世纪50年代初美国数学家R.E.Bellman等人在研究多阶段决策过程(multistep decision process)的优化问题时,提出了著名的最优化原理(principle of optimality)   动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。我们希望找到具有最优值的解。基本思想是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。 动态规划算法的有效性依赖于问题本身所具有的两个重要性质: 1.最优子结构:   当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质。 2.重叠子问题: 来源: https://www.cnblogs.com/khnl/p/11639278.html

贪婪算法核心

亡梦爱人 提交于 2019-11-30 19:56:27
通常解决并理解一个动态规划问题需要以下 4 个步骤: 利用递归回溯解决问题 利用记忆表优化(自顶向下的动态规划) 移除递归的部分(自底向上的动态规划) 使用技巧减少时间和空间复杂度 来源: https://www.cnblogs.com/ZJPaang/p/11638557.html

动态规划训练之六

时光毁灭记忆、已成空白 提交于 2019-11-30 19:49:55
https://www.luogu.org/problem/P2467 这是一道好题 题目描述 求1-n排列组成的波动数列的个数 分析首先肯定是个dp没错了,考虑设计方案, dp[i,j] ,表示用 1-i 的排列最后一个为 j 的方案数 dp[i,j] 相当于 dp[i-1,k] 中原排列大于等于 j 的数都加1,再把 j 插到末尾后的新合法排列的方案数 类似test10.7的排列题 答案有 “M" 型与 "W" 型,显然方案数是一样的,这里只考虑 "W" 型的,最后把答案*2就行了 这时你可能会有疑问,为什么偶数是枚举 [1,j-1] ,而奇数是枚举 [j,i-1] , 因为只考虑 “W” 形态的,所以 奇数 一定是 山峰 的,而 偶数 一定 山谷 ; 所以奇数枚举的一定要比前一个位置上的数大,偶数枚举的一定要比前一个位置上的数小 #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define N 4211 #define M(a) ((a)<=mod?(a):(a-mod)) inline int read(){ int x=0,f=1; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-')f=-1; c=getchar(); }

二叉苹果树--树上动态规划

流过昼夜 提交于 2019-11-30 19:31:49
#include<cstring> #include<iostream> #include<cstdio> #include<algorithm> #include<vector> #define maxn 200 using namespace std; int val[maxn]; struct Node { int p; int len; Node(int a, int b) :p(a), len(b) {} }; vector<Node>G[maxn]; void insert(int be, int en,int len) { G[be].push_back(Node(en, len)); } int n, m; int l[maxn], r[maxn]; int dfs1(int x,int fa) {//建立树 for (int i = 0; i < G[x].size(); i++) { int p = G[x][i].p; if (p == fa) continue; val[p] = G[x][i].len; if (!l[x]) l[x] = p; else r[x] = p; dfs1(p, x); } return 0; } int dp[maxn][maxn]; int dfs(int i, int j) {//编号i,有j个树枝 if (j == 0)

动态规划训练之四

别等时光非礼了梦想. 提交于 2019-11-30 19:31:48
https://www.luogu.org/problem/P2473 看数据范围,不是搜索就是状压 于是就开心状压,先不要管他什么期望 DP模型很容易想到, 用 f[i,S] 表示到了第i轮,宝物是否取过的状态为S的最大期望得分。 但这个模型存在问题: 可能在第i轮无法到达状态S为什么呢? 比如 你枚举 i 的时候是从 1 开始的,而此时你又要枚举 j 从 0 到 1<<(n-1) , 肯定是不行的啊,那怎么办? 所以,这里把定义换一下 f[i,S] 表示在第 1 轮到第 i-1 轮内宝物是否取过的状态为 S ,第 i 轮到第 K 轮的最大期望得分, 那么这样就可以通过 逆推 进行转移了。 转移方程为: 对于任意一个 1<=k<=n 1、如果S包含的状态满足取第k种宝物的条件,则可以取或不取。不取则为 f[i+1,S] ,综合取则为 max(f[i+1,S],f[i+1,S|(1<<k-1)]+val[k]) 。 2、如果S包含的状态不满足取第k种宝物的条件,则不能取,即 f[i,S]+=f[i+1,S] 。 而这里求的是 期望值 ,上面求的东西覆盖了第i轮取了所有n种宝物的情况,所以在每一个状态计算完之后,把 f[i,S] 除以n即为期望平均值。 最后答案为 f[1,0] 。 #include <cmath> #include <cstdio> #include

掌握动态规划,助你成为优秀的算法工程师

余生颓废 提交于 2019-11-30 18:08:25
1.导论 相信很多同学已经在为今年的校招做准备了,随着AI的火热,越来越多的同学涌入了算法的行当之中。那去年校招的算法岗是有多火热?在知乎上看到这么一条帖子,先不说内容哈,足足400w+的阅读量啊。 不光是计算机或软件专业的学生,很多电子,通信,自动化等相关专业的同学也吸引了进来。当然,这应该是件好事。但是相当一部分同学,在学习的过程中,尤其是刚入门的时候,可能会有这样一个疑问:算法工程师的算法,为什么不是指《算法导论》中的算法(以下称为经典算法,用以区分),而是指机器学习里的算法。都叫算法(Algorithm),但好像不是一回事啊,两者有什么关系,又有什么区别呢? 本文试图通过动态规划这一经典算法中的重要内容,同时又在机器学习算法中有着广泛的应用,来简单探讨一下这两种“算法”。 2.动态规划 首先,动态规划(Dynamic Programming)是《算法导论》中的重要章节,同时也是在机器学习算法中有着非常重要应用的一种优化算法。可以说是,无论是否是算法工程师都应该掌握的一种算法。再功利一点说,动态规划也是诸多面试官特别喜欢考的一种题型,下面就带大家稍微温故一下。 按照教材[1]的介绍,动态规划通常需要按如下4个步骤来进行设计: 刻画一个最优解的结构特征。 递归地定义最优解的值。 计算最优解的值,通常采用自底向上的方法。 利用计算出信息构造一个最优解。 简单点说

[动态规划] 背包问题

不羁岁月 提交于 2019-11-30 15:18:00
问题描述 01背包问题:有n个物品,每个物品有体积和价值两个属性,现在有一个固定容量的背包,要将这些物品放入背包内,使得背包内物品总价值最大,问要如何放? 注意:每个物品的数量为1。 设$V = 14$。 为了描述方便起见,我们用$c_1,c_2,c_3,....c_n$表示物品的体积, 用$w_1,w_2,w_3,....w_n$表示物品的价值,用$V$表示背包的容量,$n$表示物品的数量。 动态规划描述 背包问题是动态规划问题的一种,和分治算法一样,它是将一个大问题分成一个一个的小问题,然后找到大问题和小问题之间的递推式,将一个个小问题组合成大问题, 并且通常要求这些 小问题也要达到最优 。能用动态规划解决的问题一般含有两种性质: 最优子结构 和 重叠子问题。 动态规划从本质上讲就是穷举法, 但是它的却比一般的算法效率要高, 这就是因为它能剪去重叠的子问题,使得总体复杂度不那么高。 解决方法 1.递归方法 我们先从最容易入手的地方开始,用递归的方法来解这个问题。 首先对于每个物品,我们的选择只有两个:放或者不放。我们将所有的可能都穷举出来,就可以得到下面这个树状图(只画了前四个结点): 这个树上每一个分支都只能选一个,每一行就代表一个子问题。我们用$F(i, v_i)$表示前$i$个物品放入背包内的最大价值(即最优方案),此时这个$v_i$指的是放入前$i

LeetCode-动态规划

一个人想着一个人 提交于 2019-11-30 15:14:53
72. Edit Distance 最短编辑距离 https://leetcode.com/problems/edit-distance/ 题目:给定两个单词Word 1和Word2,找到将word 1转换为Word2所需的最小操作数。允许对一个单词执行以下3种操作:插入字符、删除字符、替换字符。 思路: class Solution { public int minDistance(String word1, String word2) { int a = word1.length(); int b = word2.length(); int[][] dp = new int[b+1][a+1]; dp[0][0] = 0; for(int i = 1; i < a+1; i++) { dp[0][i] = i; } for(int i = 1; i < b+1; i++) { dp[i][0] = i; } for(int j = 1; j < b+1; j++) { for(int i = 1; i < a+1; i++) { if(word1.charAt(i-1) == word2.charAt(j-1)){ dp[j][i] = dp[j-1][i-1]; } else { int temp = Math.min(dp[j-1][i], dp[j-1][i-1]);

动态规划解决01背包问题

北战南征 提交于 2019-11-30 12:35:32
/*本程序旨在利用动态规划解决有价值的0-1背包问题*/ /*物品的大小和价值以及背包的大小保存在一个放置在E盘根目录下的的csv文件中*/ #include <iostream> #include <sstream> #include <fstream> #include <vector> #include <string> #include <algorithm> using namespace std; int main() { ifstream in("E://packageProblem.csv"); string line; string field; int packageSize; int objectNum; getline(in, line); stringstream ss; istringstream sin; ss << line; ss >> packageSize; ss.clear(); getline(in, line); ss << line; ss >> objectNum; ss.clear(); int *objectSize = new int[objectNum]; int *objectValue = new int[objectNum]; int sizePointer = 0; int valuePointer = 0;