日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

斜率优化初步

發布時間:2024/3/12 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 斜率优化初步 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

use:https://imgse.com/

引言(瞎扯),聽_rqy大佬說斜率優化更應該叫做截距優化
rqy大佬說的好像很有道理qwq。


斜率優化,概括的來講就是優化形如\(f_i=a_i+Max^{i-1}_{j=0}(y_j-k_ix_j)\)其中\(k_i\)是遞減的(或\(Max\)換成\(Min\)\(k_i\)是遞增的)的一種方法

其中\(a_i\)是一個和\(j\)無關的常數,然后我們看\(Max\)中,就只有\(k_i\)是與\(j\)無關的常數

如果暴力\(dp\)的話,時間復雜度就是\(O(N^2)\),我們還需考慮優化

狀態是\(O(N)\)的,已經夠優了。考慮優化轉移到\(O(1)\)

我們將方程中的\(y_j,x_j\)拿出來,看做點\((x_j,y_j)\),然后放到笛卡爾坐標系中(嘿,真洋呼)

像這樣

然后將直線\(y=kx+b\)帶入

然后我們選取一點,算出將直線\(y=kx+b\)平移至改點,然后算出平移后直線的截距
\(y-y_i=k(x-x_i)\)
\(y=kx+y_i-kx_i\)截距就是\(y_i-kx_i\)。發現就是所需的數值

然后我們揭下來就是利用其加速決策.
假設我們在進行\(k_i\)時的決策,我們,我們可以找到一條\(y=kx\)的直線,然后在我們1~i點組成的圖形中找到一個截距最大的點,就可以進行轉移了。很巧的是,這條符合條件的直線只經過這個點,不經過其他點之間之間的連線(或只有多個點)

such as

然后我們還有個性質,\(k_i\)是遞減的,然后我們在進行決策時候,就可以讓上圖中紅線的繞這個圖形進行旋轉,隨著\(i\)的增加,逐漸轉到綠線所到的位置。

就像這樣(ps:作圖時沒考慮好qwq

然后我們就會發現,有些點是我們考慮都不會考慮的,如下圖所示

這一部分我們就丟掉不管了,反正他不是最優的。

然后我們發現我們進行完這一步,就好像凸出來一塊。然后我們按照如此規則,修整一下整個圖形

這個東西叫做凸殼

到此,我們先回憶一下。如何利用凸殼進行決策

然后對于一個\(i\),我們先取得\(k_i\),然后再從凸殼\(1-i\)中找到一條直線\(y=kx+b\),使得其截距最大。

而所找到的直線不會穿過凸殼內部。

凸殼是怎么來的呢?在\(k\)遞減的情況下,繞所有點所圍成的。(就像墻上一堆釘子,拿一根小木棍繞著轉,決定小木棍的方向的是最外邊的兩個點,而不是其內部的點,而最外面的點相鄰的,對小木棍方向有決定的點連線,形成的圖形就是凸殼(馬馬虎虎qwq))


好,然后我們再來考慮維護凸殼,以及如何具體使用凸殼

如何維護插入一個點,使用單調隊列,在我們改變直線斜率時,也就是旋轉直線時,如果是順時針旋轉,則不用干其他的操作。如果是逆時針旋轉,則需要進行一些維護操作

如下圖

需要我們介入,將\(C\)點刪除,那如何程序實現呢?

先不急,我們再來看一個更極端的栗子。

我們如何操作呢?

貪心的想,我們只比較\(E,F\)兩個點,然后我們分別算一下新增點到\(E,F\)兩條直線的斜率,若發現\(F\)的斜率比\(E\)的直線的斜率大,那我們就刪除\(F\)\(E\)點何時刪除呢?

在我們比較\(D,E\)是刪除,所以我們就使用單調隊列,里面是斜率單減的。

void push(int i)//將第i個點加入 {while(tail-head>=1)//隊列中至少要留兩個元素,另外,因為我比較毒瘤,所以我的隊首和隊尾都是實指{int a=queue[tail],b=queue[tail-1];//去出后兩個元素if((y[i]-y[a])*(x[i]-x[b])>(x[i]-x[a])*(y[i]-y[b]))//比較,聽_rqy說是叉積//好高級的樣子,其實就是兩個截距式比較(我也不知道叫什么,必修二一點也沒學,其實讀者將左右對調對調,成為分數的形式,就能看出來為什么了。寫成乘法快,還可以避免爆精)tail--;else break;}queue[++tail]=i; }

然后就是取隊首

暴力的想,每次按遍歷所有點,取最大值

然后發現,竟然是單峰呀。然后我們再來改變斜率(遞減),發現峰值所在的位置竟然遞增

好好好,單調隊列qwq。

其實這里你可以想象,一條直線就真的在凸殼上旋轉,然后就會有個支點,使得這條直線繞他旋轉,這個點就是當時直線截距最大的點。然后總是要離開這個支點的,然后到了下一個支點,下一個支點就是在另一個斜率時的峰頂qwq

void pop(int i) {while(tail-head>=1)//需要保存兩個點{int a=queue[head],b=queue[head+1];//取出前兩個值if(y[a]-k[i]*x[a]<y[b]-k[i]*x[b])//保持單調性,排除掉不是最優解head++;else break;}return ; }

end.

轉載于:https://www.cnblogs.com/Lance1ot/p/9418936.html

總結

以上是生活随笔為你收集整理的斜率优化初步的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。