关于dp优化的问题

来源:互联网 发布:淘宝客服名 编辑:程序博客网 时间:2024/06/08 15:46

  dp已经是一个很优化的算法,能用很短的时间解决问题能将复杂度降到很低。但是dp也存在优化,这样使dp更加有效。

  dp的优化分:单调队列优化、斜率优化、四边形优化。  

  我觉的单调队列优化是斜率优化的一种特殊形式。

下面通过例题来了解dp的优化问题。

1.斜率优化:

hdu 3507 Print Article 

题意:大概题意就是要输出N个数字,分成连续的多段,每一段它的费用是:这串数字和的平方加上一个常数M。

题解:状态方成 dp[i] = dp[j] + M + (sum[i]-sum[j-1])^2  Here

hdu 2993 MAX Average Problem (dp斜率优化)

题意:给出N个正整数,求最大的,长度大于K的某一段的平均值

题解:很明显的斜率优化,(sum[i]-sum[j])/(i-j) 那么直接队列优化。具体看代码  Here

注意一点,这题异常的坑爹,scanf读入直接超时了!!!是的你没听错scanf超时,而且int会爆。那么我们可以用自读入。写个函数解决。

2.单调队列优化

hdu3401_分析降维_队列优化

题意:

给出未来T天股票的买进、卖出的价格的最大上限问如何获利最大。

题解:Here

                  不买不卖            买                       卖
     dp = max{ dp[i-1][j] , dp[x][y] - (j-y)*APi[i] , dp[x][y] + (y-j)*BPi[i] }     .....(1)
                           x<i-w, 0<j-y<MaxP       x<i-w, 0<y-j<MaxP
                           
令pre=i-w-1;
==>  dp = max { dp[i-1][j], dp[pre][k] - APi[i]*(j-k) , dp[pre][k] + BPi[i]*(k-j) } ......(2)
    为什么能推出这步呢?我们观察第一个dp方程里面有dp[i-1][j] 每次都会和这个比较那么之前的
    这个dp[i-1][j]在之前就已经和dp[i-2][t1]比较过了,那么dp[i-2][t1]之前也和dp[i-3][t2]比较
    过了,一直递归下去发现,i-w-1之前的就已经都比较过了,那么式子(1)从0——>i-w-1滚动比较就是
    多余的。由此得出式子(2)的结论。


==>  以买入为例子:dp + j*dp[pre][k] = dp[pre][k] + k*APi[i];                      ......(3)



==>  那么久可以用单调的队列去优化,因为很明显左边的值随着 k 单调递增而递增。

hdu 3530 Subsequence(dp单调队列优化)

题意:

给出n个数的序列,找到这样的区间满足 m<=最大的数-最小的数<=k ,要求求出这中区间的最大长度

题解:用两个队列优化出处理O(nlogn) 一个队列存最大值,一个队列存最小值,每次更新,满足条件的入队列,不满足条件的删除队头。Here


3.四边形优化

poj 1160

题意:给出n个村庄,村庄是一条直线排好的,并且给出每个村庄到直线最左边初始点的距离。现在要建立m个邮局,于是引入一个距离S{各个村庄到最近的邮局的距离和}。那么现在问题来了如何使得这个S的值最小?

题解:定义这样的方程 dp[i][j] = min{ dp[i-1][k] + w[k+1][j] } 我们可以看出这个方程满足这样的模型 s[i][j] = s[i][k] + s[k+1][j] 那么我们可以断定用平行四边形优化。那么定义mark[i][j]表示最大的k就可以把复杂度降到O(n^2)

注意一点,在循环的第二层是倒着推的,为什么?很显然如果正着推的话会产生后效性,因为我们加入了mark[i][j]这个辅助的原因,如果没有这个辅助可以正的推,加了之后因为mark[i][n+1]=n,如果正着推发现mark[i][j]都没计算出来,显然dp过程就错了,倒着推很明显mark[i][n+1]是计算出来的,这样递推下去才不会有没计算的。Here

hdu 3480 Division(dp四边形优化)

题意:

给出n个数,让你把它分成m个集合,不同集合间允许有相同元素,所有集合的并集为全集,使得集合的代价和最小。单个集合的代价为集合中最大值与最小值的差值。

题解:Here

这题看过去发现序列可以任意排列,好像不能用dp,很棘手的样子,那么我们可以这样分析一下对于4个数1 4 7 9 我们分成两个集合怎么和分?如果1和7 4和9显然不能最有,1和4 7和9呢?是最优了! 那么这个例子我们看出如果将序列从小到大的排序,跨越了很多个数来取集合的话会发现还不如尽量相邻的优。你这样想,相邻的间隔肯定比跨越的间隔小啊,那么跨越这取有什么意义呢?

用贪心解决了这个问题后,我们就可以解决这个问题了。

排序完后:

状态方程:dp[i][j] = dp[i][j]= max{ dp[i-1][k]+(val[j]-val[k+1])*(val[j]-val[k+1]) }

四边形优化mark[i][j]标记

hdu 3506 Monkey Party(dp四边形优化)

题意:一群猴子围成圈,每个猴子互相不认识,猴王要给大家互相认识,每个猴子认识别人需要一个时间花费,而且A猴子认识B猴子,则A猴子认识的所有猴子和B猴子认识的所有猴子都能认识,这个代价为所有AB猴子认识的猴子的时间花费和。

很明显的环形的区间dp和取石子问题很像。

状态方程:dp[i][j]= max{ dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1] }

注意一点:区间类dp的四边形标记和非区间类的有点不同,具体要体会理解。

题解:Here


以下这题要好好理解,两种方法的优劣 :

hdu 2829 Lawrence (dp斜率优化||四边形优化)

题意:

给出很多一段路线,由n个点组成,每个点有价值,定义某个区间[i,j]上的价值为这个区间没两个点两两相乘的和,现在可以选择m个点炸掉,这样可以分成m+1段,总的价值就是每段价值的和。那么现在问题来了,如何分段使得价值对低呢?

题解:Here

0 0
原创粉丝点击