国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

斜率優化dp 學習筆記

2019-11-08 02:38:29
字體:
來源:轉載
供稿:網友

從一個問題開始 真正理解斜率優化dp orz ISA

1 問題

Apio 2010 特別行動隊

1.1 題意簡述

給出一個序列x1,x2...xn,將其劃分成若干個連續的區間,每一段區間[l,r]的價值為ax2+bx+c,其中x=∑i=lrxi 現在你需要最大化序列的價值

1.2 數據范圍

對于20%的數據,n≤1000 對于100%的數據,1≤n≤106?5≤a≤?1|b|≤107|c|≤1071≤xi≤100

1.3 討論

1.3.1 20pts

f(i)表示將序列的前i個劃分若干段的最大價值,si表示序列的前綴和 直接根據題意,可以列出狀態轉移方程 f(i)=max{f(j)+a?(si?sj)2+b?(si?sj)+c},1≤j<i 然后直接dp就可以了 時間復雜度O(n2)

1.3.2 100pts

數據范圍只能允許一個O(n)級別的算法

將轉移方程進一步展開,能得到 f(i)=max{f(j)+as2i?2asisj+as2j+bsi?bsj+c},1≤j<i 將其順序調整,寫成下面的形式 f(i)=max{?2asjsi+f(j)+as2j?bsj+as2i+bsi+c},1≤j<i 觀察這個式子

首先,最后三項,只和a,b,c以及si有關。換句話說,在求f(i)的值時,這三項是與j的選取無關的,我們稱之為常數項 對于常數項,可以直接將其拿到max之外 f(i)=max{?2asjsi+f(j)+as2j?bsj}+as2i+bsi+c,1≤j<i

然后再觀察前面4項,可以發現si是與j的選取無關的,只與si的選取有關;而其余都只與j的選取有關,而與i的選取無關 si有什么性質? si為正項序列的前綴和,顯然它一定是對于1...n單調遞增的 在求解f(i)的過程中,我們也一定是按照1...n的順序求,也就是說,在求解f(i)的過程中si單調遞增

我們考慮將前四項抽象成一條直線 令y=kx+b 其中k=?2asjb=as2j?bsj 也就是說,對于每一個j(1≤j≤n),都有一條確定的直線 那么在求解f(i)的時候,對于之前的一個確定的j,將si帶入解析式就能求出這個j所對應的函數值 如果枚舉每一個j,求出相應的函數值來更新f(i)的話,實際上就是O(n2)dp的方法了 但是我們現在不能枚舉,需要直接求出,也就是說,需要確定一條能取到最優值的直線

所以說,什么是斜率優化dp? 對于每一個i(1≤i≤n),將i抽象成一條直線 求f(i)時,求之前的所有直線在自變量為某一個數時的最優值 根據直線的斜率和自變量的增減關系,維護出一個O(n)的算法 明白了這個之后,就已經基本上明白了斜率優化的大體過程

1.4 題解

對于這道題來說 由于?5≤a≤?1,可以得出k>0,即所有直線的斜率為正 由于si單增,求f(i)的過程中,順次加入直線,直線的斜率也始終單增 維護一個斜率單增的單調雙端隊列,兩個指針l,r

每一次加入一條直線yi之前,判斷隊首的兩條直線ylyl+1si處的函數值,如果yl≤yl+1,說明直線yl已不是最優值,并且以后也不可能成為最優值,將其出隊 計算f(i),此時最優的直線即為隊首的直線yl 加入直線yi,如果yiyr?1已經將yr完全覆蓋,那么將yr彈出

舉個栗子 這里寫圖片描述 在求解f(3)的時候,需要查看f(1)f(2)所表示的兩條直線在s3處的函數值,然后取最大 如圖所示,顯然選y2比選y1要優 由于si單增,以后在求解f(4)、f(5)...的時候,這兩條直線在s4、s5...處的函數值y1也不可能比y2更優,所以y1實際上就已經可以扔掉了

還有一種情況 這里寫圖片描述 可以發現,順次插入y1,y2,y3這三條直線,因為要取最大值,y2實際上已經被y1y3完全覆蓋了,無論si取何值,它都已經不可能成為最優的答案,這個時候y2也可以扔掉了 實際上就是維護了一個下凸殼啊

我剛開始不明白為什么完全覆蓋的要扔掉,不扔直接做不行么 這里有一個反例 這里寫圖片描述 此時y1y3已經將y2完全覆蓋,應該扔掉 但是如果不扔掉的話,查詢此時在s4處的最優值 顯然y1>y2,這個時候會默認y1即為最優值,不會將y1彈出 而實際上y3才是真正的最優值 所以判斷是否有兩條直線將另外一條覆蓋是完全必要的

如何判斷兩條直線已經被另一條直線覆蓋? 知識儲備:初中數學 如上圖,令y1=k1x+b1,y2=k2x+b2,y3=k3x+b3 則求y1y3的交點橫縱坐標為 k1x+b1=k3x+b3 x=b3?b1k1?k3 y=k1b3?b1k1?k3+b1 然后求y2x處的函數值 y2=k2b3?b1k1?k3+b2y2≤yk2b3?b1k1?k3+b2≤k1b3?b1k1?k3+b1 b3?b1k1?k3≤b2?b1k1?k2 (k1?k3)?(b2?b1)≤(k1?k2)?(b3?b1) 那么直線y2已經被y1y3完全覆蓋 如果斜率為負或者斜率單減的話別搞錯了正負號就好

這就是整個斜率優化的過程

1.5 代碼

代碼簡潔清晰明了

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>using namespace std;#define LL long long#define N 1000005int n,l,r;LL a,b,c,x;int q[N];LL s[N],f[N];LL K(int j) {return -2*a*s[j];}LL B(int j) {return f[j]+a*s[j]*s[j]-b*s[j];}LL Y(int i,int j) {return K(j)*s[i]+B(j);}bool cover(int x1,int x2,int x3){ LL w1=(K(x1)-K(x3))*(B(x2)-B(x1)); LL w2=(K(x1)-K(x2))*(B(x3)-B(x1)); return w1<=w2;}int main(){ scanf("%d",&n); scanf("%lld%lld%lld",&a,&b,&c); for (int i=1;i<=n;++i) scanf("%lld",&x),s[i]=s[i-1]+x; l=r=0; for (int i=1;i<=n;++i) { while (l<r&&Y(i,q[l])<=Y(i,q[l+1])) ++l; f[i]=Y(i,q[l])+a*s[i]*s[i]+b*s[i]+c; while (l<r&&cover(i,q[r],q[r-1])) --r; q[++r]=i; } 2 斜率優化dp

2.1 常見形式

斜率優化dp的狀態轉移方程有一些比較特殊的性質:

求解最值每一個狀態能轉化成一條直線在求解某一個狀態時,因變量為求解的狀態值,自變量為與這個狀態相關的量自變量滿足單調性,斜率滿足單調性

2.2 基本方法

將狀態轉移方程化成能表示成直線的形式找出自變量、因變量、斜率、截距,討論自變量的單調性、斜率的正負及單調性維護單調雙端隊列,維護上凸/下凸殼

3 相關題目

題目難度盡量遞增 ps 原來寫的代碼都好丑

bzoj1597 土地購買 http://blog.csdn.net/clove_unique/article/details/51244336 bzoj3156 防御準備 http://blog.csdn.net/clove_unique/article/details/51250213 bzoj3437 小P的牧場 http://blog.csdn.net/clove_unique/article/details/51297305 bzoj1010 hnoi2008 玩具裝箱 http://blog.csdn.net/Clove_unique/article/details/51225398 bzoj3675 apio2014 序列分割 http://blog.csdn.net/clove_unique/article/details/51297313 bzoj1096 zjoi2007 倉庫建設 http://blog.csdn.net/clove_unique/article/details/51244357 bzoj4518 sdoi2016 征途 http://blog.csdn.net/clove_unique/article/details/51224588


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 南宫市| 博兴县| 新昌县| 永嘉县| 武城县| 天水市| 介休市| 公安县| 上蔡县| 大足县| 普兰店市| 星子县| 安平县| 福鼎市| 孟州市| 平舆县| 铜陵市| 藁城市| 乐亭县| 凤阳县| 静乐县| 深州市| 丹寨县| 同仁县| 武功县| 诸城市| 泽州县| 东阿县| 昌乐县| 通山县| 南丹县| 健康| 赞皇县| 如东县| 历史| 墨脱县| 河池市| 辽中县| 昌图县| 尼木县| 昭觉县|