动态规划

ACM 中常用的算法有哪些?

て烟熏妆下的殇ゞ 提交于 2020-01-30 22:22:13
在网上看到别人ACM学习的心得,转载过来,源地址不记得了,当时是百度的。内容如下: 网络上流传的答案有很多,估计提问者也曾经去网上搜过。所以根据自己微薄的经验提点看法。 我ACM初期是训练编码能力,以水题为主(就是没有任何算法,自己靠动脑筋能够实现的),这种题目特点是麻烦,但是不难,30-50道题目就可以了。 然后可以接触一下基础的算法,我感觉搜索方向的比较不错,可以解决很多问题,深搜,广搜,然后各种剪枝能力的锻炼。 搜索感觉不错了就可以去看看贪心,图论,和动态规划方向的了。图论有最短路径,最小生成树,网络流,拓扑排序等等很多,动态规划先去书上看经典例子,最长公共子序列等。各种变形的题目。 数学是ACM中极具杀伤力的武器,我一向很羡慕数学好的队友,精力有限自己数学方面的算法只能说入门。这方面经典的数论,组合数学方面的比较多,计算几何是很重要的,经典模型要熟悉,最近点对,二维三维,凸包以及各种应用。 数据结构方面的就比较多了,基础的堆,栈,队列,并查集,二叉查找树,红黑树,trie树,hash表等等。 用C++参赛的话STL要熟悉,有时候很有帮助,里面的queue,list,map,stack等。 ACM到后来算法就成了工具,不断的靠自己意淫一个新的解法来解决问题是最开心的事情了。我们学校ACM一直是一届带一届的,老师只提供经济上的援助

经典中的经典算法 动态规划(详细解释,从入门到实践,逐步讲解)

随声附和 提交于 2020-01-30 17:04:13
动态规划的重要性就不多说,直接进入正题 首先,我们看一下官方定义: 定义: 动态规划算法是通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推(或者说分治)的方式去解决。 动态规划算法的基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。 基本思想与策略编辑: 由于动态规划解决的问题多数有重叠子问题这个特点,为减少重复计算,对每一个子问题只解一次,将其不同阶段的不同状态保存在一个二维数组中。 (来自百度百科) 说实话,没有动态规划的基础很难看懂,但是也能从中看出一些信息,下面我翻译成人话: 首先是拆分问题 ,我的理解就是根据问题的可能性把问题划分成一步一步这样就可以通过递推或者递归来实现. 关键就是这个步骤,动态规划有一类问题就是从后往前推到,有时候我们很容易知道:如果只有一种情况时,最佳的选择应该怎么做.然后根据这个最佳选择往前一步推导,得到前一步的最佳选择 然后就是定义问题状态和状态之间的关系 ,我的理解是前面拆分的步骤之间的关系,用一种量化的形式表现出来,类似于高中学的推导公式,因为这种式子很容易用程序写出来,也可以说对程序比较亲和

巧用记忆化搜索代替暴力递归(洛谷P1464题题解,Java语言描述)

强颜欢笑 提交于 2020-01-30 15:44:59
题目要求 P1464题目链接 分析 如果……你信了这题干,真的写了递归……TLE警告!!! 所以,就需要优化嘛…… [−9223372036854775808,9223372036854775807]这个范围,就是C的 longlong / Java的 long 诶,算是一种数很大但还有良心的提示吧。 这题比较适合记忆化搜索,这也是我第一次写 记忆化搜索 的题解诶,就扯一扯…… 一般说来,动态规划总要遍历所有的状态,而搜索可以排除一些无效状态。更重要的是搜索还可以剪枝,可能剪去大量不必要的状态,因此在空间开销上往往比动态规划要低很多。记忆化算法在求解的时候还是按着自顶向下的顺序,但是每求解一个状态,就将它的解保存下来,以后再次遇到这个状态的时候,就不必重新求解了。这种方法综合了搜索和动态规划两方面的优点,因而还是很有实用价值的。 对于本题的话,只要一个记忆化储存就可以避免大量运算量(大佬们都说这玩意和递推/动态规划差不多)。 主要思路就是 开一个三维数组 ,把每一个“w”函数的值储存起来,下一次就可以 直接调用 ,节省大量时间。 使用的时候还要先想,记忆化的数组要开多大。对于这个题来说,输入数据在long(Java)范围内,对于每一组a,b,c都使用一个变量来进行记忆化是不现实的。 但是,根据题意,当a<0 or b<0 or c<0时,返回值都是1,当a>20 or b>20

1071: 数塔 (动态规划)

江枫思渺然 提交于 2020-01-30 15:29:48
题目描述 PIPI在CSU的某个角落发现了一座金字塔,而且这座金字塔是由数字组成的(如下图所示),现在PIPI想到塔顶去看看,它可以从底层任意一个数字出发逐层爬上去。PIPI每次可以爬至上一层相邻的数字上。 现在PIPI想知道,它如何选择爬上去的路径,使该路径经过的数字和最大? 输入 多组数据 每个测试实例的第一行是一个整数N(1 <= N <= 100),表示数塔的高度,接下来用N行数字表示数塔,其中第i行有个i个整数,且所有的整数均在区间[0,99]内。 输出 对于每个测试实例,输出可能得到的最大和,每个实例的输出占一行。 样例输入 5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 样例输出 30 【思路】 //数塔问题 #include<iostream> #include<string.h> using namespace std; int main(void) { int n; int f[100][100] = {0}; int dp[100][100] = {0};//状态数组 while(scanf("%d",&n)!=EOF){ memset(f,0,sizeof(f)); memset(dp,0,sizeof(dp)); //输入数塔 for(int i=1;i<=n;i++) for(int j=1;j<=i;j++) cin>>f[i][j];

动态规划 背包问题

荒凉一梦 提交于 2020-01-30 07:34:07
详细解读背包问题 0/1背包问题: 有N件物品和一个容量为V的背包,第i件物品消耗的容量为Ci,价值为Wi,求解放入哪些物品使背包中总价值最大。 仔细想想,这里每个物品只有一个,对于每个物品而言,只有两种选择,装入或不装入,装入记为1,不装入为0,我们不能将物品进行分割,比如只拿半个是不允许的。这就是这个问题被称为0/1背包问题的原因。 在选择的过程中,我们每做出一种选择,都会将一种情况分裂成两种,最终我们会得到一张决策图: 定义函数KS(i,j) 代表当前背包剩余容量为j时,前i个物品最佳组合所对应的价值 对于第i个物品,有两种可能: 背包剩余的容量不足以装下第i个物品,此时KS(i,j)等于KS(i-1,j) 背包剩余容量可以装下第i个物品,此时需要进行判断,因为装下该物品不一定会使最终结果是最优组合,此时我们在两中情况中选择最优情况如果不装该物品,则价值为KS(i-1,j),装下该物品的话,价值为KS(i-1,j-wight[i])+value[i] 状态转移方程 f[i][v]=max{ f[i-1][v],f[i-1][v-w[i]]+val[i] },考录问题“将前i个物品放入背包中的最大价值”,可能存在两种情况,即存在第i个物品和不存在第i个物品,我们只需在其中取最优解即可。 对于这个问题的子问题,这里有必要详细说明一下。原问题是,将n件物品放入容量为c的背包

85.最大矩形

梦想与她 提交于 2020-01-30 02:40:13
给定一个仅包含 0 和 1 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。 示例: 输入 : [ [ "1" , "0" , "1" , "0" , "0" ] , [ "1" , "0" , "1" , "1" , "1" ] , [ "1" , "1" , "1" , "1" , "1" ] , [ "1" , "0" , "0" , "1" , "0" ] ] 输出 : 6 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/maximal-rectangle 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 完整代码 基本思想 动态规划+84.求柱状图中的最大矩形的栈思想 动态规划 将每一行看成一个整体,利用动态规划的思想,需要求出当前行中的每一列中连续1的个数(特别注意:一定要将当前行考虑在内) 如何求该列中连续1的个数? 在这里并不是真正意义上的连续1的个数,而是包括当前行的那个值向上面的行延伸的最大值。举例:[[1],[1],[0],[1]]这一列连续1的个数是2,当这里考虑到最后一行,连续1的个数是1,也就是最后一行的1 参考下图: leetcode class Solution { public : int maximalRectangle ( vector < vector <

动态规划:华为练习题:合唱队排队

*爱你&永不变心* 提交于 2020-01-30 00:47:51
题目描述 计算最少出列多少位同学,使得剩下的同学排成合唱队形 说明: N位同学站成一排,音乐老师要请其中的 ( N - K ) 位同学出列,使得剩下的K位同学排成合唱队形。 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为 1 , 2 …,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足存在i( 1 <= i <= K)使得T1 < T2 < . . . . . . < Ti - 1 < Ti > Ti + 1 > . . . . . . > TK。 你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。 输入描述 : 整数N 输出描述 : 最少需要几位同学出列 示例 1 输入 8 186 186 150 200 160 130 197 200 输出 4 ''' #list1=[186,186,150,200,160,130,197,200] #list1=[186,186,150,200,201,210,151,152,153] #list1=[150,186,186,170] #n=len(list1) ''' 方法 1 :利用bisect_left函数,每次寻找该元素在序列中的绝对位置,我们 用一个数组来记录顺序递增数列的寻找情况,首先在数组中插入原数组的第一个数,每次 插入新的数时都扫描一次递增数组

算法训练 K好数(Java动态规划)

非 Y 不嫁゛ 提交于 2020-01-28 18:26:47
【问题描述】 如果一个自然数N的K进制表示中任意的相邻的两位都不是相邻的数字,那么我们就说这个数是K好数。求L位K进制数中K好数的数目。例如K = 4,L = 2的时候,所有K好数为11、13、20、22、30、31、33 共7个。由于这个数目很大,请你输出它对1000000007取模后的值。 输入格式 输入包含两个正整数,K和L。 输出格式 输出一个整数,表示答案对1000000007取模后的值。 样例输入 4 2 样例输出 7 数据规模与约定 对于30%的数据,KL <= 106; 对于50%的数据,K <= 16, L <= 10; 对于100%的数据,1 <= K,L <= 100。 【解题思路】 这题提示用动态规划解,那就用动态规划吧! 用数组 dp[ i ][ j ] 来存储结果, i 表示位数, j 存储K好数的个数 当 i = 1 时,即长度为1时,所有的数字都是K好数,因为没有数字相邻的情况。 当 i >= 2 时, dp[ i ][ j ] = dp[ i-1 ][ j ] + dp[ i ][ j ] 即当 i = 2,j = 1 时,开头数为1,能组成不相邻的数字只有3,所以 dp[ 2 ][ 1 ] = dp[ 1 ][ 1 ] + dp[ 1 ][ 3 ] = 2 当 K=4 L=2 时,K好数的个数就是分别为1、2、3开头的个数相加,即 dp[ 2 ]

动态规划---数字三角形

﹥>﹥吖頭↗ 提交于 2020-01-28 17:14:05
题目描述: 在数字三角形中寻找一条从顶部到底边的路径,使得路径上所经过的数字之和最大,路径上的每一步都只能往左下或右下走,只需要求出这个最大和即可,不必给出具体路径 三角形的行数大于1小于等于100,数字为 0 - 99 解题思路: 用 二维数组 存放数字三角形 D( r , j ) :第 r 行第 j 个数字( r 、j 从1开始算) MaxSum( r , j ) : 从D( r , j )到底边的各条路径中,最佳路径的数字之和 问题:求 MaxSum( 1 ,1 )(典型的递归问题) 从 D( r ,j )出发,下一步只能走D( r + 1 ,j )或者D( r + 1 ,j + 1 ),故对于 N行 的三角形: if ( r == N ) //到底部时 MaxSum ( r , j ) = D ( r , j ) else MaxSum ( r , j ) = Max ( MaxSum ( r+ 1 , j ) , MaxSum ( r + 1 , j + 1 ) ) + D ( r , j ) # include <iostream> # include <algorithm> # define MAX 101 using namespace std ; int D [ MAX ] [ MAX ] ; int n ; int MaxSum ( int i , int j

最优二叉搜索树—动态规划

天涯浪子 提交于 2020-01-28 15:58:22
最优二叉搜索树是建立在搜索树的基础上的一种最优解,一开始我也很纠结为什么会有查找不成功和查找成功的概念,后来才开始明白后来懂了如何去做,如果这点还没有明白那很难去懂什么是最优二叉搜索树,下面按照题目讲解主要内容: 我们先来声明一下如何求二叉搜索树的权重 形状1的平均查找次数 形状2的平均查找次数 计算的方程 知道了如何计算平均查找次数,我们下面求解一下如何求解最优二叉搜索树问题 将四个合起来 拼成一个个基本的子树暂时命名为a1,a2,a3 a1和a2合并有两种情况 计算得出第一种权重较小,故选择第一种形状为T[1][2] 同理计算出T[2][3]应该为第一种模型 这是最终有a1和a2以及a2和a3形成的最小二叉搜索树的子树 当我们求解T[1][3]时,实际上我们求解的是由T[1][2]与a3构成的,以及a1与T[2][3]构成的其中找到最优解 得出最优解由形状一取得 这是动态规划的动态矩阵以及状态转移方程 来源: CSDN 作者: 李小白努力努力努力ing 链接: https://blog.csdn.net/lixindayup/article/details/104098907