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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

初探斜率优化

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

dp是一個在noip必考的項目(據說今年又要出新算法了),于是在機房老師的引導下,學習了斜率優化dp(真是一個好東西)

下面說一下我的心得吧:

? 首先對于斜率優化呢

? 這是一種無法用直接單調隊列優化的算法,由于它的轉移方程中存在著一個或多個會根據當前狀態有關的量,故單調隊列無法直接優化,而這里就用到了斜率優化。

? 下面給出一道例題

P3195 [HNOI2008]玩具裝箱TOY

題目描述

P教授要去看奧運,但是他舍不下他的玩具,于是他決定把所有的玩具運到北京。他使用自己的壓縮器進行壓縮,其可以將任意物品變成一堆,再放到一種特殊的一維容器中。P教授有編號為?1\cdots N1?N?的?NN?件玩具,第?ii?件玩具經過壓縮后變成一維長度為?C_iCi??.為了方便整理,P教授要求在一個一維容器中的玩具編號是連續的。同時如果一個一維容器中有多個玩具,那么兩件玩具之間要加入一個單位長度的填充物,形式地說如果將第?ii?件玩具到第?jj?個玩具放到一個容器中,那么容器的長度將為?x=j-i+\sum\limits_{k=i}^{j}C_kx=j?i+k=i∑j?Ck??制作容器的費用與容器的長度有關,根據教授研究,如果容器長度為?xx?,其制作費用為?(X-L)^2(X?L)2?.其中?LL?是一個常量。P教授不關心容器的數目,他可以制作出任意長度的容器,甚至超過?LL?。但他希望費用最小.

感謝@ACの666 提供的Latex題面

輸入輸出格式

輸入格式:

?

第一行輸入兩個整數N,L.接下來N行輸入Ci.1<=N<=50000,1<=L,Ci<=10^7

?

輸出格式:

?

輸出最小費用

?

輸入輸出樣例

輸入樣例#1:?復制

5 4 3 4 2 1 4

輸出樣例#1:?復制

1

我們發現這題的dp方程十分的簡單

? f[i]=min{f[j]+(sum[i]-sum[j]+i-j-l-1)^2}(看不懂或推不出的請學好dp再來)

方便起見 我們定義xa[i]=sum[i]+i? xb[i]:=sum[i]+i+l+1

轉移方程變為了f[i]=min{f[j]+(xa[i]-xb[j])^2}(0<=j<i)

?數據范圍一看就不是O(n^2)能承受的,我們必然要對其中的一維狀態或是一維轉移優化

若是優化狀態。。。。(O(1)的狀態那不就變貪心了嗎???,某些題的貪心性質就是這樣被發現的)

但是這題我們沒有發現可以貪心的線索,那我們只能優化轉移了

這里我們發現對于一個新的i的轉移有一個sum[i]和它-l的平方影響?,很明顯無法簡單使用單調隊列優化轉移
在這里,我們不妨假設有j<k,對于i的轉移k比j優

則就會得到

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?f[j]+(xa[i]-xb[j])^2>f[k]+(xa[i]-xb[k])^2

打開這個式子:? ? ? ? ?f[j]+xa[i]^2+xb[j]^2-2*xa[i]*xb[j]>f[k]+xa[i]^2+xb[k]^2-2*xa[i]*xb[k]

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? f[j]+xb[j]^2-(f[k]+xb[k]^2)<2*xa[[i]*(xb[j]-xb[k])

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?這里就會很容易發生一些錯誤

由于j<k,那么這題的sum數組又是單調遞增的,則xb[j]-xb[k]其實是一個負數,當我們把他除過去的時候,不等號就會改變方向

我們發現? ? ??(f[j]+xb[j]^2-(f[k]+xb[k]^2))/(2*(xb[j]-xb[k]))>xa[i]

?左邊只剩下了關于j和k的量,不妨用g(j,k)表示(f[j]+xb[j]^2-(f[k]+xb[k]^2))/(2*(xb[j]-xb[k]))

于是我們發現當g(j,k)<xa[i]時k就會更優

反之g(j,k)>xa[i]時j就會更優,神奇的事情發生了

我們發現如果存在j1<j2<j3,g(j1,j2)>g(j2,j3)時無論xa[i]如何取值,在這里j2這個轉移一定不會是最優的

那我們只要維護一個G單調不降就可以了

同時發現若xa[i]大于了單調隊列中最小的一個,后面的元素都會沒有用,所以在隊首維護一個單調性把小于xa[i]的值都彈出,每次取隊首的元素作為最優的轉移對象,那么時間復雜度就會降到O(n)的時間范圍,一個元素只會進隊一次出隊一次,均攤O(1)

那么為什么要叫斜率優化呢,我們發現g(j,k)里可以抽象的把j和k看做兩個點而g(j,k)可以看做是j到k的斜率,維護g的單調性就相當與維護一個二維的凸包,每次出現xa[i],就是相當與用一條斜率為xa[i]的線去在這個凸包上截取最近的一個點。

那么斜率優化也就講到這里了

安利一波代碼

var
n,l,i,j,head,tail:longint;
a,sum,xb,xa,f,q:array[0..1000000] of int64;
function g(a,b:longint):double;
begin
? exit((f[a]-f[b]+xb[a]*xb[a]-xb[b]*xb[b])/((xb[a]-xb[b])<<1));
end;
begin
? readln(n,l);
? for i:=1 to n do
? begin
? ? read(a[i]);
? ? sum[i]:=sum[i-1]+a[i];
? ? xa[i]:=sum[i]+i;
? ? xb[i]:=sum[i]+i+l+1;
? end;
? xb[0]:=l+1;
? head:=1; tail:=1;
? q[1]:=0;
? for i:=1 to n do
? begin
? ? while (head<tail) and (g(q[head+1],q[head])<xa[i]) do inc(head);
? ? j:=q[head];
? ? f[i]:=f[j]+(xa[i]-xb[j])*(xa[i]-xb[j]);
? ? while (head<tail) and (g(q[tail],q[tail-1])>g(q[tail-1],i)) do dec(tail);
? ? inc(tail); q[tail]:=i;
? end;
? writeln(f[n]);
end.

轉載于:https://www.cnblogs.com/by-w/p/9608092.html

總結

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

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