动态规划之队列优化
- 格式:doc
- 大小:149.50 KB
- 文档页数:9
排队问题的三种方法
排队问题的三种方法如下:
1. 经典方法:经典方法是解决排队问题的一种方法。
这种方法基于队列的基本概念,将排队系统中的元素看作队列中的元素,并考虑一些基本的操作,如插入、删除和移动元素。
经典方法通常包括以下步骤:
- 确定元素数目和优先级。
- 创建一个初始队列,并确定队列长度。
- 确定哪些元素需要移动到新的位置。
- 确定哪些元素需要删除。
- 执行操作,并将结果更新队列。
2. 动态规划方法:动态规划方法是解决排队问题的一种重要方法。
这种方法将问题划分为若干个子问题,并使用状态转移方程来解决问题。
状态转移方程通常包括以下步骤:
- 确定当前队列中元素数目和优先级。
- 根据优先级和元素数目,确定新状态。
- 在新状态中,根据优先级和元素数目,确定新队列的长度和元素数目。
- 根据新状态,解决问题。
3. 贪心算法:贪心算法是解决排队问题的一种重要方法。
这种方法假设元素具有一些基本性质,例如都具有一定的优先级和数目,并根据这些性质来解决问题。
贪心算法通常包括以下步骤:
- 确定当前队列中元素数目和优先级。
- 根据优先级和元素数目,确定新元素的可能性。
- 确定最可能的新元素,并插入到队列中。
- 如果新元素插入后,队列长度发生变化,重新考虑最可能的新元素。
动态规划算法的优化技巧福州第三中学毛子青[关键词] 动态规划、时间复杂度、优化、状态[摘要]动态规划是信息学竞赛中一种常用的程序设计方法,本文着重讨论了运用动态规划思想解题时时间效率的优化。
全文分为四个部分,首先讨论了动态规划时间效率优化的可行性和必要性,接着给出了动态规划时间复杂度的决定因素,然后分别阐述了对各个决定因素的优化方法,最后总结全文。
[正文]一、引言动态规划是一种重要的程序设计方法,在信息学竞赛中具有广泛的应用。
使用动态规划方法解题,对于不少问题具有空间耗费大、时间效率高的特点,因此人们在研究动态规划解题时更多的注意空间复杂度的优化,运用各种技巧将空间需求控制在软硬件可以承受的范围之内。
但是,也有一部分问题在使用动态规划思想解题时,时间效率并不能满足要求,而且算法仍然存在优化的余地,这时,就需要考虑时间效率的优化。
本文讨论的是在确定使用动态规划思想解题的情况下,对原有的动态规划解法的优化,以求降低算法的时间复杂度,使其能够适用于更大的规模。
二、动态规划时间复杂度的分析使用动态规划方法解题,对于不少问题之所以具有较高的时间效率,关键在于它减少了“冗余”。
所谓“冗余”,就是指不必要的计算或重复计算部分,算法的冗余程度是决定算法效率的关键。
动态规划在将问题规模不断缩小的同时,记录已经求解过的子问题的解,充分利用求解结果,避免了反复求解同一子问题的现象,从而减少了冗余。
但是,动态规划求解问题时,仍然存在冗余。
它主要包括:求解无用的子问题,对结果无意义的引用等等。
下面给出动态规划时间复杂度的决定因素:时间复杂度=状态总数*每个状态转移的状态数*每次状态转移的时间[1]下文就将分别讨论对这三个因素的优化。
这里需要指出的是:这三者之间不是相互独立的,而是相互联系,矛盾而统一的。
有时,实现了某个因素的优化,另外两个因素也随之得到了优化;有时,实现某个因素的优化却要以增大另一因素为代价。
因此,这就要求我们在优化时,坚持“全局观”,实现三者的平衡。
动态规划之队列优化浙江省镇海中学 贺洪鸣【例1锯木场选址】(CEOI2004)从山顶上到山底下沿着一条直线种植了n 棵树。
当地的政府决定把他们砍下来。
为了不浪费任何一棵木材,树被砍倒后要运送到锯木厂。
木材只能按照一个方向运输:朝山下运。
山脚下有一个锯木厂。
另外两个锯木厂将新修建在山路上。
你必须决定在哪里修建两个锯木厂,使得传输的费用总和最小。
假定运输每公斤木材每米需要一分钱。
任务你的任务是写一个程序:从标准输入读入树的个数和他们的重量与位置 计算最小运输费用将计算结果输出到标准输出 输入输入的第一行为一个正整数n ——树的个数(2≤n ≤20 000)。
树从山顶到山脚按照1,2……n 标号。
接下来n 行,每行有两个正整数(用空格分开)。
第i +1行含有:v i ——第i 棵树的重量(公斤为单位)和 d i ——第i 棵树和第i +1棵树之间的距离,1≤v i ≤10 000,0≤d i ≤10 000。
最后一个数d n ,表示第n 棵树到山脚的锯木厂的距离。
保证所有树运到山脚的锯木厂所需要的费用小于2000 000 000分。
输出输出只有一行一个数:最小的运输费用。
样例输入 91 22 13 31 1 32 1 6 2 1 1 2 1 1在解决这一问题时,首先我们要明确,将锯木厂建立在相邻两棵树之间是没有任何意义的,否则我们可以将这样的锯木厂上移到最近的一棵树处,此时运送上方树木的费用减少,运送下方树木的费用没有变化,总费用降低。
为了方便讨论,我们先作如下定义:假设山脚锯木场处也有一棵树,编号为1n +,并且v[n+1]=d[n+1]=0。
][i sumw 表示第1棵树到第i 棵树的质量和,即∑==ij j w i sumw 1][][。
][i sumd 表示第1棵树到第i 棵树的距离,即∑-==11][][i j j d i sumd 。
特别的,有0]1[=sumd ,表示第1棵树到自己的距离为0。
最优化多目标规划动态规划多目标规划是指在决策问题中同时考虑多个目标的优化问题,其目标可能相互矛盾或者相互关联。
动态规划是一种通过将问题划分为子问题并利用子问题的最优解来求解整体最优解的方法。
将多目标规划与动态规划结合起来,可以解决一些具有多个相互关联目标的决策问题。
下面将介绍最优化多目标规划动态规划的原理和应用举例。
1.定义决策变量:确定需要作出的决策,并定义决策变量。
2.建立状态转移方程:将问题划分为多个子问题,并建立它们之间的状态转移方程。
状态转移方程描述了子问题之间的关系,通过子问题之间的转移可以得到整体问题的最优解。
3.确定初始状态和边界条件:确定初始状态和边界条件,即子问题的初始状态和边界条件,用于递归地求解子问题。
4.递推求解:使用动态规划的递推求解方法,从初始状态开始,逐步求解子问题,直到求解出整体的最优解。
5.分析最优解:根据求解结果分析得到的最优解,并根据需要进行调整和优化。
假设有一家公司要进行产品的生产安排,公司有多个产品需要安排生产,每个产品有不同的生产时间和利润,同时公司还要考虑生产能力的限制和产品订单的要求。
问题可以建立如下的数学模型:决策变量:对于每个产品,决定其生产数量。
目标函数:最大化总利润。
约束条件:生产时间不能超过生产能力限制,同时生产数量要满足订单要求。
利用动态规划方法可以将问题分解为多个子问题,以子问题的最优解作为动态规划的递推依据。
具体步骤如下:1.将产品的生产时间和利润作为状态,根据时间顺序划分为多个子问题。
2.定义状态转移方程,将子问题的最优解与前面子问题的最优解关联起来。
3.初始状态为生产时间为0的情况,边界条件为订单要求。
4.递推求解,根据状态转移方程求解每个子问题的最优解。
5.分析最优解,确定每个产品的生产数量,以及总利润。
通过最优化多目标规划动态规划的方法,可以在满足多个目标和约束条件的情况下,求解出最优的决策方案。
这种方法可以应用于生产调度、资源分配、物流配送等领域,帮助企业做出合理的决策,达到优化目标。
动态规划算法的优化技巧福州第三中学毛子青[关键词] 动态规划、时间复杂度、优化、状态[摘要]动态规划是信息学竞赛中一种常用的程序设计方法,本文着重讨论了运用动态规划思想解题时时间效率的优化。
全文分为四个部分,首先讨论了动态规划时间效率优化的可行性和必要性,接着给出了动态规划时间复杂度的决定因素,然后分别阐述了对各个决定因素的优化方法,最后总结全文。
[正文]一、引言动态规划是一种重要的程序设计方法,在信息学竞赛中具有广泛的应用。
使用动态规划方法解题,对于不少问题具有空间耗费大、时间效率高的特点,因此人们在研究动态规划解题时更多的注意空间复杂度的优化,运用各种技巧将空间需求控制在软硬件可以承受的范围之内。
但是,也有一部分问题在使用动态规划思想解题时,时间效率并不能满足要求,而且算法仍然存在优化的余地,这时,就需要考虑时间效率的优化。
本文讨论的是在确定使用动态规划思想解题的情况下,对原有的动态规划解法的优化,以求降低算法的时间复杂度,使其能够适用于更大的规模。
二、动态规划时间复杂度的分析使用动态规划方法解题,对于不少问题之所以具有较高的时间效率,关键在于它减少了“冗余”。
所谓“冗余”,就是指不必要的计算或重复计算部分,算法的冗余程度是决定算法效率的关键。
动态规划在将问题规模不断缩小的同时,记录已经求解过的子问题的解,充分利用求解结果,避免了反复求解同一子问题的现象,从而减少了冗余。
但是,动态规划求解问题时,仍然存在冗余。
它主要包括:求解无用的子问题,对结果无意义的引用等等。
下面给出动态规划时间复杂度的决定因素:时间复杂度=状态总数*每个状态转移的状态数*每次状态转移的时间[1]下文就将分别讨论对这三个因素的优化。
这里需要指出的是:这三者之间不是相互独立的,而是相互联系,矛盾而统一的。
有时,实现了某个因素的优化,另外两个因素也随之得到了优化;有时,实现某个因素的优化却要以增大另一因素为代价。
因此,这就要求我们在优化时,坚持“全局观”,实现三者的平衡。
排队问题的三种方法排队问题是一类经典的图论问题,通常涉及到在一条流水线上安排生产任务或者服务请求,使得所有任务或者请求都能够及时完成,本文将介绍三种解决排队问题的方法。
方法一:贪心算法贪心算法是一种简单的算法思想,通过每次选择最优解来得到全局最优解。
在排队问题中,贪心算法可以通过不断尝试最坏情况来得到最优解。
具体来说,我们可以从最后一个待安排的任务开始,依次将当前任务和已经安排的任务进行交换,直到任务队列为空。
这种方法能够保证所有的任务都能够及时完成,但是可能会出现任务队列为空的情况,也就是没有任务可以安排。
方法二:动态规划算法动态规划算法是一种通过构建状态转移方程来求解问题的方法,通常适用于问题的规模较大或者最优解不是唯一的情况。
在排队问题中,我们可以将任务队列看作是状态,任务等待时间和执行任务的时间看作是状态转移方程。
具体来说,我们可以从最后一个待安排的任务开始,依次计算出当前任务需要等待的时间和已经安排的任务需要执行的时间,然后将当前任务和已经安排的任务进行交换,直到任务队列为空。
这种方法可以得到最优解,但是需要计算大量的状态转移方程。
方法三:图论算法图论算法是一种通过构建图来分析问题的方法,通常适用于问题的规模较大或者最优解不是唯一的情况。
在排队问题中,我们可以将任务队列看作是一个图,任务之间的等待关系看作是边,然后通过最小生成树或者贪心算法来得到最优解。
具体来说,我们可以从最后一个待安排的任务开始,依次将当前任务和已经安排的任务进行交换,直到任务队列为空。
这种方法可以得到最优解,但是需要计算大量的边。
以上三种方法是解决排队问题的常见方法,贪心算法适用于没有最优解的情况,动态规划算法适用于有多个最优解的情况,图论算法适用于问题规模较大的情况。
此外,排队问题的拓展应用还有很多,例如排队论、排队系统、排队论模型等。
1D/1D 动态规划优化初步所谓1D/1D 动态规划,指的是状态数为O(n),每一个状态决策量为O(n)的动态规划方程。
直接求解的时间复杂度为O(n 2),但是,绝大多数这样的方程通过合理的组织与优化都是可以优化到O(nlogn)乃至O(n)的时间复杂度的。
这里就想讲一讲我对一些比较初步的经典的优化方法的认识。
本文中不想进行过多的证明与推导,主要想说明经典模型的建立、转化与求解方法。
由于本人认识与水平相当有限,如果出现什么错误与疏漏,还请大牛多多指正。
另外,也希望大牛们更多地向我们介绍一下有关动态规划优化的更深入的东西。
本文中使用两种方式表示一个函数:f(x)与f[x],用方括号表示的函数值可以在规划之前全部算出(常量),而用圆括号表示的函数值必须在规划过程中计算得到(变量)。
无论是什么函数值一经确定,在以后的计算中就不会更改。
经典模型一:11()min{()[,]}x i f x f i w i x -==+ 相信这个方程大家一定是不陌生的。
另外,肯定也知道一个关于决策单调性的性质: 假如用k(x)表示状态x 取到最优值时的决策,则决策单调性表述为: ,()()i j k i k j ∀≤≤,当且仅当:,[,][1,1][1,][,1]i j w i j w i j w i j w i j ∀≤+++≤+++,对于这个性质的证明读者可以在任意一篇讲述四边形不等式的文章中找到,所以这里不再重复。
而且,从实战的角度来看,我们甚至都不需要验证w 函数的这个性质,最经济也是最可靠的方法是写一个朴素算法打出决策表来观察(反正你总还是要对拍)。
当然,有的时候题目要求你做一点准备工作,去掉一些明显不可能的决策,然后在应用决策单调性。
这是上述性质也许会有点用处。
正如前文中所述,我们关注的重点是怎样实现决策单调性。
有了决策单调性,怎样高效地实现它呢?很容易想到在枚举决策的时候,不需要从1开始,只要从k(x-1)开始就可以了,但这只能降低常数,不可能起到实质性的优化。
山东师大附中陈键飞前言自古以来就是NOIP的重要考察内容,在联赛中占的分量大。
对选手能力有一定要求,需要能够熟练地建立动态规划模型。
需要大量做题,初学者不易掌握其思想。
目录基础:基本概念背包问题——一类典型应用 进阶:更多的问题树形DP状态压缩优化:减少状态数目减少状态转移(决策)时间基本概念最长上升子序列状态:f[i]能完全地表示出问题某个或某些本质相同的形态决策:f[i]=min(f[j]+1)状态由哪个状态转移得到阶段:每个i前面的阶段决定后面的阶段,后面的阶段由前面的状态转移得到基本概念石子合并状态f[i,j]决策f[i,j]=min(f[i,k]+f[k+1,j])+w[i,j] 阶段j-i (区间大小)基本概念无后效性后面阶段的状态只受前面阶段的状态的影响 对于任意两个状态,只能单向的进行转移基本概念拓扑图(有向无环图)无后效性f[i]=min(f[j])+1基本概念 非拓扑图(可能有环) 有后效性a →b →c ?b →c →a ?a bc 51111基本概念最优子问题问题最优,只需子问题最优,与到达子问题的路径无关3 5 24 6f(5)最优,只需f(4)最优,与f(4)是怎么到达的无关与路线具体是3 4 6还是2 4 6无关基本概念最优子问题输出1~n中∑(A(i,p[i]))最大的排列f(i)表示用1~n组成的长度为i的序列? 与到达子问题的路径有关!1 4 3 →6 ?4 2 3 →6 ?基本概念无后效性、最优子问题是否能满足与状态的表示,状态的转移,阶段的划分有关背包问题——一类典型应用 给定n个货币,面值各不相同,问能否凑出m元钱f[i,j]表示前i个货币能否凑出j元f[i,j] = f[i-1,j] (不选j)or f[i-1,j-w[i]](选j)背包问题——一类典型应用 给定n种货币,每种无限多个,面值各不相同,问能否凑出m元钱f[i,j]表示前i种货币能否凑出j元f[i,j]=f[i-1,j] or f[i,j-w[i]]背包问题——一类典型应用 给定n种货币,第i种有A i个,面值W i,问能否凑出m 元钱将每种货币i拆成A i个价值为W i的货币O(m∑A i)将每种货币i拆成价值为W i,2W i,4W i,8W i……的货币O(m∑log A i)单调队列O(mn) ,暂时跳过背包问题——一类典型应用 给定n种货币分为k组,每组只能选一个,问能否凑出m元f[i,j,k]表示用前1~i-1组和第i组的前j个能否凑出k元。
动态规划算法时间效率的优化动态规划是一种用于解决优化问题的算法思想,在很多实际场景中都有广泛的应用。
然而,动态规划算法在处理问题的过程中,可能会面临一些时间效率的优化问题。
为了提高动态规划算法的时间效率,可以从以下几个方面进行优化。
1.减少重复计算:动态规划算法通常需要计算大量的子问题,但有些子问题可能会被重复计算。
这会导致算法效率下降。
可以通过使用备忘录或者动态规划表来记录已经计算过的子问题的结果,以避免重复计算。
这样可以大幅提高算法的效率。
2.剪枝策略:在动态规划算法中,可以通过剪枝策略来减少不必要的计算。
剪枝策略可以是其中一种条件限制,当不满足该条件时,直接跳过计算,这样可以极大地减少计算量。
3.优化状态转移方程:动态规划算法的核心是状态转移方程。
优化状态转移方程可以通过寻找问题的规律,减少计算量。
可以尝试化简状态转移方程,将复杂的问题转化为简单的问题,这样可以减少计算时间。
4.按需计算:动态规划算法通常需要计算所有的子问题,然后根据子问题的结果来求解最终问题。
但实际上,并不是所有的子问题都必须计算。
可以根据问题的特点,在需要的时候再进行计算,避免不必要的计算,提高算法效率。
5.并行计算:在一些情况下,可以采用并行计算的方式来提高动态规划算法的效率。
通过将问题分解成多个子问题,分别计算,然后将结果合并,可以加速算法的执行。
6.优化空间复杂度:动态规划算法通常需要使用额外的内存空间来存储计算过程中的中间结果。
优化空间复杂度可以使用状态压缩技术,将中间结果压缩成一个变量,从而减少内存的使用。
7.选择合适的数据结构:对于一些特殊的问题,可以根据问题的特点选择合适的数据结构来优化算法效率。
比如,对于一维数组问题,可以使用队列或者堆来进行优化;对于二维数组问题,可以使用矩阵来进行优化。
8.分治思想:有一些问题可以使用分治思想来优化动态规划算法。
将问题分解成多个子问题,分别求解,然后将子问题的结果合并,可以提高算法的效率。
1D/1D 动态规划优化初步所谓1D/1D 动态规划,指的是状态数为O(n),每一个状态决策量为O(n)的动态规划方程。
直接求解的时间复杂度为O(n 2),但是,绝大多数这样的方程通过合理的组织与优化都是可以优化到O(nlogn)乃至O(n)的时间复杂度的。
这里就想讲一讲我对一些比较初步的经典的优化方法的认识。
本文中不想进行过多的证明与推导,主要想说明经典模型的建立、转化与求解方法。
由于本人认识与水平相当有限,如果出现什么错误与疏漏,还请大牛多多指正。
另外,也希望大牛们更多地向我们介绍一下有关动态规划优化的更深入的东西。
本文中使用两种方式表示一个函数:f(x)与f[x],用方括号表示的函数值可以在规划之前全部算出(常量),而用圆括号表示的函数值必须在规划过程中计算得到(变量)。
无论是什么函数值一经确定,在以后的计算中就不会更改。
经典模型一:11()min{()[,]}x i f x f i w i x -==+ 相信这个方程大家一定是不陌生的。
另外,肯定也知道一个关于决策单调性的性质: 假如用k(x)表示状态x 取到最优值时的决策,则决策单调性表述为: ,()()i jk i k j ∀≤≤,当且仅当: ,[,][1,1][1,][,i j w i j w i j w i j w i j∀≤+++≤+++,对于这个性质的证明读者可以在任意一篇讲述四边形不等式的文章中找到,所以这里不再重复。
而且,从实战的角度来看,我们甚至都不需要验证w 函数的这个性质,最经济也是最可靠的方法是写一个朴素算法打出决策表来观察(反正你总还是要对拍)。
当然,有的时候题目要求你做一点准备工作,去掉一些明显不可能的决策,然后在应用决策单调性。
这是上述性质也许会有点用处。
正如前文中所述,我们关注的重点是怎样实现决策单调性。
有了决策单调性,怎样高效地实现它呢?很容易想到在枚举决策的时候,不需要从1开始,只要从k(x-1)开始就可以了,但这只能降低常数,不可能起到实质性的优化。
动态优化问题常见解法动态优化问题是计算机科学中的一个重要领域,它涉及到在给定约束条件下,寻找最优解的问题。
在解决动态优化问题时,常用的几种解法包括贪心法、动态规划法和分治法。
贪心法贪心法是一种简单而常用的动态优化问题解法。
它的基本思想是在每一步都选择当前状态下最优的解,希望通过每一步的最优选择达到全局最优解。
贪心法通常适用于一些较为简单、局部最优即能得到全局最优的情况。
然而,贪心法并不适用于所有动态优化问题,特别是那些需要考虑长远后果的问题。
在使用贪心法解决问题时,需要仔细分析问题的特性以确定贪心策略的适用性。
动态规划法动态规划法是一种比较常用且灵活的动态优化问题解法。
它通过建立一个状态转移方程来逐步求解问题。
具体而言,动态规划法将原问题分解为子问题,然后利用已解决的子问题的解来求解更大规模的问题。
动态规划法通常需要建立一个动态规划表格或数组来存储子问题的解,以便在求解大问题时可以利用已经求解过的子问题的解。
动态规划法的关键在于确定子问题的解以及状态转移方程的定义。
分治法分治法是一种将问题分割为更小的子问题并分别解决的解法。
它的基本思想是将原问题划分为多个相互独立且结构相似的子问题,然后递归地解决这些子问题。
最后,将子问题的解合并得到原问题的解。
分治法通常适用于一些较为复杂的问题,能够有效地解决大规模问题。
然而,分治法并不是适用于所有动态优化问题,具体问题需要根据其特性来确定是否适用分治法进行求解。
总结在解决动态优化问题时,贪心法、动态规划法和分治法是常见的解法。
贪心法适用于一些较为简单且局部最优即为全局最优的问题。
动态规划法通过求解子问题来逐步求解大问题,适用于各类动态优化问题。
分治法通过将问题划分为子问题并递归求解,适用于复杂的大规模问题。
在选择合适的解法时,需要充分考虑问题的特性和约束条件。
每种解法都有其优缺点,在实际应用中需要仔细分析问题的性质以确定最合适的解法。
基于线程队列动态规划法的GPU 性能优化魏雄1,2,胡倩1,王秋娴1,闫坤1,许萍萍3(1.武汉纺织大学数学与计算机学院,湖北武汉430000;2.国防科技大学计算机学院,湖南长沙410073;3.湖北城市建设职业技术学院,湖北武汉430205)收稿日期:2021-03-120引言GPU 在大数据和人工智能领域表现出惊人的计算能力,随着GPU 的普及,在生命科学、航空航天和国防中提供了较强的计算能力,特别是在2020年新冠肺炎基因序列测序和疫情传播预测等方面表现突出。
大数据和AI 时代的到来使计算任务加重,面对应用的不同资源需求,GPU 的资源单核未充分利用[1]。
为了解决GPU 资源利用率不足的问题,国内外学者提出一些方法,例如Justin Luitjens [1]提出了并发内核执行(CKE )来支持在GPU 上并发运行多个内核,并且GPU 自身架构也支持线程级并行性(Thread-level Parallelism ,TLP )[2],但大量并发线程会导致严重的带宽问题,内存延迟而无法及时处理的内存请求有可能会导致流水线暂停,降低整体性能。
为了更好地提升性能,利用GPU 的资源,本文提出了线程队列动态规划法TQDP ,从线程角度出发,通过提高线程的执行次数和提升系统吞吐量,从而提高系统性能。
1GPU新一代GPU 体系架构集成的计算资源越来越多,同时由于GPU缺乏适当的体系架构来支持共享,需要软件、硬件或者软硬件协同的方法来使用计算资源,因其复杂性导致GPU 资源利用不足,影响整体性能。
1.1GPU体系架构NVIDIA第8代GPUTuring第一次使用GDDR6DRAM 内存,并引入了新的SM体系架构,采用了可加速光线追踪的RT Core,以及可用于AI推理的全新Tensor Core[3]。
虽然GPU 架构经过一代代的变化,但是大致架构改动不大。
图1是一个基线GPU架构图,GPU有多个流多处理器(Streaming Multiprocessor,SM),在每个SM中,计算资源包括算术逻辑单元(ALU)、特殊函数单元(SFU)以及寄存器,片上内存资源包括只读纹理缓存和常量缓存、L1数据缓存(D-cache)和共享内存。
动态规划应用动态规划解决问题的思路与技巧动态规划应用 - 动态规划解决问题的思路与技巧动态规划(Dynamic Programming)是一种常见的算法思想,用于解决一些具有重叠子问题和最优子结构性质的问题。
通过将大问题划分为小问题,并将小问题的解存储起来以避免重复计算,可以在一定程度上优化问题的求解过程。
本文将介绍动态规划的应用,并提供一些思路与技巧。
一、动态规划的基本思路动态规划问题通常可以由以下步骤解决:1. 定义状态:将问题划分成若干子问题,并确定每个子问题需要记录的状态。
2. 定义状态转移方程:通过分析子问题之间的关系,建立状态转移方程,以表达子问题的最优解与更小规模子问题的关系。
3. 初始化边界条件:确定最小规模子问题的解,并初始化状态转移方程中需要用到的边界条件。
4. 递推求解:按照状态转移方程的定义,从较小规模的子问题开始逐步推导出较大规模的问题的解。
5. 求解目标问题:根据最终推导出的状态,得到原始问题的最优解。
二、动态规划的技巧与优化1. 滚动数组:为了降低空间复杂度,可以使用滚动数组来存储状态。
滚动数组只记录当前状态与之前一部分状态相关的信息,避免了存储所有状态的需求。
2. 状态压缩:对于某些问题,可以将状态压缩成一个整数,从而大幅减小状态的数量。
例如,当问题中涉及到某些特定的组合或排列时,可以使用二进制位来表示状态。
3. 前缀和与差分数组:对于某些问题,可以通过计算前缀和或差分数组,将问题转化为求解累加或差对应数组中的某个区间的值的问题,从而简化计算过程。
4. 贪心思想:有些动态规划问题可以结合贪心思想,在每个阶段选择局部最优解,然后得到全局最优解。
5. 双重循环与多重循环:在实际解决问题时,可以使用双重循环或多重循环来遍历状态空间,求解问题的最优解。
三、动态规划的实际应用动态规划广泛应用于各个领域,包括但不限于以下几个方面:1. 最短路径问题:例如,求解两点之间的最短路径、最小生成树等。
动态规划之队列优化浙江省镇海中学 贺洪鸣【例1锯木场选址】(CEOI2004)从山顶上到山底下沿着一条直线种植了n 棵树。
当地的政府决定把他们砍下来。
为了不浪费任何一棵木材,树被砍倒后要运送到锯木厂。
木材只能按照一个方向运输:朝山下运。
山脚下有一个锯木厂。
另外两个锯木厂将新修建在山路上。
你必须决定在哪里修建两个锯木厂,使得传输的费用总和最小。
假定运输每公斤木材每米需要一分钱。
任务你的任务是写一个程序:从标准输入读入树的个数和他们的重量与位置 计算最小运输费用将计算结果输出到标准输出 输入输入的第一行为一个正整数n ——树的个数(2≤n ≤20 000)。
树从山顶到山脚按照1,2……n 标号。
接下来n 行,每行有两个正整数(用空格分开)。
第i +1行含有:v i ——第i 棵树的重量(公斤为单位)和 d i ——第i 棵树和第i +1棵树之间的距离,1≤v i ≤10 000,0≤d i ≤10 000。
最后一个数d n ,表示第n 棵树到山脚的锯木厂的距离。
保证所有树运到山脚的锯木厂所需要的费用小于2000 000 000分。
输出输出只有一行一个数:最小的运输费用。
样例输入 91 22 13 31 1 32 1 6 2 1 1 2 1 1在解决这一问题时,首先我们要明确,将锯木厂建立在相邻两棵树之间是没有任何意义的,否则我们可以将这样的锯木厂上移到最近的一棵树处,此时运送上方树木的费用减少,运送下方树木的费用没有变化,总费用降低。
为了方便讨论,我们先作如下定义:假设山脚锯木场处也有一棵树,编号为1n +,并且v[n+1]=d[n+1]=0。
][i sumw 表示第1棵树到第i 棵树的质量和,即∑==ij j w i sumw 1][][。
][i sumd 表示第1棵树到第i 棵树的距离,即∑-==11][][i j j d i sumd 。
特别的,有0]1[=sumd ,表示第1棵树到自己的距离为0。
c[i]表示在第i 棵树处建一个锯木厂,并且将第1到第i 棵树全部运往这个伐木场所需的费用。
显然有c[i]=c[i-1]+sumw[i-1]*d[i-1]。
特别的,有c[1]=0。
w[j,i]表示在第i 棵树处建一个锯木场,并且将第j 到第i 棵树全部运往这个锯木场所需的费用。
则w[j,i]=c[i]-c[j-1]-sumw[j-1]*(sumd[i]-sumd[j-1])。
特别的,当i<=j 时w[j,i]=0。
综上可知,求出所有sumw[i],sumd[i]与c[i]的时间复杂度为O(n),此后求任意w[j,i]的时间复杂度都为O(1)。
设f[i]表示在第i 棵树处建立第二个锯木场的最小费用,则有11[]min {[][1,][1,1]}j i f i c j w j i w i n ≤=≤-=+++++。
直接用这个式子计算的时间复杂度为)(2n O ,由于问题规模太大,直接使用这一算法必然超时,因此我们必须对算法进行优化。
在讨论如何进行优化以前,我们首先证明下面这一猜想。
[猜想]如果在位置i 建设第二个锯木厂,第一个锯木厂的位置是j 时最优。
那么如果在位置i+1建设第二个锯木厂,第一个锯木厂的最佳位置不会小于j 。
证明:假设第1个锯木厂建立在第j 个处时,f[i]取得最优值,且此时j 为f[i]取得最优值时的最小值,如下图所示.此时f[i]=c[j]+w[j+1,i]+w[i+1,n+1] 则对于任意的k<j,c[k]+w[k+1,i]+w[i+1,n+1]>c[j]+w[j+1,i]+w[i+1,n+1]即求f[i+1]时,决策k 比决策j 来得差!因此,当f[i]的第一个最佳决策为j 时,f[i+1]的第一个最优决策必大于等于j!证毕!【算法的改进】令s[k,i]表示决策变量取k 时f[i]的值,即s[k,i]=c[k]+w[k+1,i]+w[i+1,n+1]。
设k1<k2,则有s[k1,i]-s[k2,i]=(c[k1]+w[k1+1,i]+w[i+1,n+1])-(c[k2]+w[k2+1,i]+w[i+1,n+1]) =(c[k1]+c[i]-c[k1]-sumw[k1]*(sumd[i]-sumd[k1]) - (c[k2]+c[i]-c[k2]-sumw[k2]*(sumd[i]-sumd[k2])=sumw[k2]*(sumd[i]-sumd[k2])- sumw[k1]*(sumd[i]-sumd[k1])1j+1 i+1 i n+1锯木厂 C[j] w[j+1,i] w[i+1,n+11 k K+1 i+1 i n+1C[k] w[k+1,i] w[i+1,n+1]1 j j+1 i+1 i n+1 锯木厂 C[j] w[j+1,i+1]w[i+2,n+1]1k K+1 i+1 in+1 C[k] w[k+1,i+1] w[i+2,n+1] c[k]+w[k+1,i]>c[j]+w[j+1,i] c[k]+w[k+1,i]+(sumw[i]-sumw[k])*d[i]>c[j]+w[j+1,i]+(sumw[i]-sumw[k])*d[i]c[k]+w[k+1,i+1]>c[j]+w[j+1,i+1] c[k]+w[k+1,i+1]+w[i+2,n+1]>c[j]+w[j+1,i+1]+w[i+2,n+1]第k+1至第i 的总重量 第i 至第i+1的距离 第j+1至第i 的总重量, 必小于第k+1至第i 的总重量=sumd[i](sumw[k2]-sumw[k1])-(sumw[k2]*sumd[k2]-sumw[k1]*sumd[k1])若s[k1,i]-s[k2,i]<0,则有:sumd[i](sumw[k2]-sumw[k1])<(sumw[k2]*sumd[k2]-sumw[k1]*sumd[k1])即(sumw[k2]*sumd[k2]-sumw[k1]*sumd[k1])/ (sumw[k2]-sumw[k1])> sumd[i]或(sumw[k1]*sumd[k1]-sumw[k2]*sumd[k2])/ (sumw[k1]-sumw[k2])> sumd[i] 我们令g[k1,k2]=不等式左边,当g[k1,k2]>sumd[i]时s[k1,i]-s[k2,i]<0。
由上面已经证明的猜想,说明决策变量j是单调的,(即f[i+1]的决策j2必大于等于f[i]时的决策j1)此时问题就好解决了。
我们可以维护一个特殊的队列k,这个队列只能从队尾插入,但是可以从两端删除。
这个队列满足k1<k2<k3<…<k p以及g[k1,k2]<g[k2,k3]<…<g[k p-1,k p]。
1.计算状态f[i]前,若g[k1,k2]<sumd[i],表示s[k1,i]-s[k2,i]>0,即决策k1没有k2优,应当删除队首,将k1,k2,指针后移,直至g[k1,k2]>sumd[i]。
此时, s[k1,i]-s[k2,i]<0, 即决策k1比k2优。
2.计算状态f[i]时,直接使用决策k1,f[i]=c[k1]+w[k1+1,i]+w[i+1,n+1]。
O(1)代价!(由当前的决策序列:sumd[i]<g[k1,k2]<g[k2,k3]<…<g[k p-1,kp]知,决策k1优于k2,k2优于k3,…,k p-1优于k p。
)3.计算状态f[i]后向队列插入新的决策i。
若g[k p-1,k p]>g[k p,i],此时,如果求某个f[r]时选择K p为决策,则k p-1决策必然没有k p好,即s[k p-1,r]-s[k p,r]>0 => g[k p-1,k p]<sumd[r]=> g[k p,i]<sumd[r]=> s[k p,r]-s[i,r]>0,此时,说明决策i必然比k p来得优表示在k p比k p-1优之前i就将比k p优,k p没必要保存。
并且,根据前面的猜想,对于以后的状态,决策i也会比k p优。
因此删除k p,将指针p前移,直至g[k p-1,k p]< g[k p,i]。
队列中的元素只会入队一次,出队一次,维护队列k的总复杂度为O(n),因此每个状态f[i]计算的均摊复杂度都为O(1),整个算法的时间复杂度为O(n)。
问题得到解决!注意:上例的决策单调性的条件是,每棵树的重量均>0,这样,重量前缀数组sumw满足单调性,才会满足第j+1至第i的总重量,必小于第k+1至第i的总重量(k<j)。
【例2仓库建设】(浙江2007L公司有N如右图所示,工厂1在山顶,工厂NL公司一般把产品直接堆放在露天,以节省费用。
突然有一天,L公司的总裁L先生接到是不同的。
第i个工厂目前已有成品Pi件,在第i个工厂位置建立仓库的费用是Ci。
对于没有建立仓库的工厂,其产品应被运往其他的仓库进行储藏,而由于L公司产品的对外销售处设置在山脚的工厂N,故产品只能往山下运(即只能运往编号更大的工厂的仓库),当然运送产品也是需要费用的,假设一件产品运送1个单位距离的费用是1。
假设建立的仓库容量都都是足够大的,可以容下所有的产品。
你将得到以下数据:工厂i距离工厂1的距离Xi(其中X1=0);工厂i目前已有成品数量Pi;在工厂i建立仓库的费用Ci;请你帮助L公司寻找一个仓库建设的方案,使得总的费用(建造费用+运输费用)最小。
【输入文件】输入文件storage.in第一行包含一个整数N,表示工厂的个数。
接下来N行每行包含两个整数Xi, Pi, Ci, 意义如题中所述。
【输出文件】输出文件storage.out 仅包含一个整数,为可以找到最优方案的费用。
【样例输入】30 5 105 3 1009 6 10【样例输出】32【样例说明】在工厂1和工厂3建立仓库,建立费用为10+10=20,运输费用为(9-5)*3 = 12,总费用32。
如果仅在工厂3建立仓库,建立费用为10,运输费用为(9-0)*5+(9-5)*3=57,总费用67, 不如前者优。
【初步分析】1.状态表示以sump[i]表示第1个工厂至第i 个工厂中的总的产品数量;以sumw[i]表示将第1个工厂至第i 个工厂的所有产中运至第i 个工厂的费用; 以w[i,j]表示将第i 个工厂至第j 个工厂的所有产中运至第j 个工厂的费用。
W[i,j]=sumw[j]-sumw[i-1]-sump[i-1]*(x[j]-x[i-1])所有的sump[1..n]、sumw[1..n]可在O(n)的总次数内算出,每个w[i,j]可以O(1)算出。