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

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

【BZOJ】1010 [HNOI2008] 玩具裝箱toy dp+斜率優化

2019-11-08 18:36:43
字體:
來源:轉載
供稿:網友

題目我就不再贅述了,題目傳送門

首先我們先來了解一下斜率優化的用處:斜率優化就是把一些特殊的dp方程化簡、變形,然后用維護單調隊列,把O(n^2)的時間復雜度降至O(n),實現程序的提速。

當然有些dp方程是無法用斜率優化的,這個我等下會進行詳細解釋的。

題目中最基本的dp方程可以很容易的想到:f[i]=min{f[j]+(i-(j+1)+s[i]-s[j]-L)^2} (0<=j<i) 其中s[i]表示Sigma(c[k]) (1<=k<=i)

我們設p[i]=s[i]+iM=L+1,則原方程可以轉化成f[i]=min{f[j]+(p[i]-p[j]-M)^2} (0<=j<i)

則:f[i]=min{f[j]+p[i]^2-2*p[i]*(p[j]+M)+(p[j]+M)^2} (0<=j<i)

若k<j且j的決策比k要好,則:f[j]+p[i]^2-2*p[i]*(p[j]+M)+(p[j]+M)^2<f[k]+p[i]^2-2*p[i]*(p[k]+M)+(p[k]+M)^2

化簡,得:f[j]+(p[j]+M)^2-f[k]+(p[k]+M)^2<2*p[i]*(p[j]-p[k])

不等式兩邊同時除以2*(p[j]-p[k]),得:(f[j]+(p[j]+M)^2-f[k]+(p[k]+M)^2)/(2*(p[j]-p[k]))<p[i] 

(f[j]+(p[j]+M)^2-f[k]+(p[k]+M)^2)/(2*(p[j]-p[k]))就是斜率g(j,k)

因為s[i]是嚴格單調上升的,所以p[i]也是嚴格單調上升的。若p[i]不是嚴格單調上升的,那么原dp方程就無法用斜率優化,因為原dp方程不滿足單調隊列的單調性。

所以,知道g(j,k)后,我們可以O(1)判斷出j比k更優。

但是,知道g(j,k)后我們并不能把時間復雜度降到O(n),我們還需要一個強有力的幫手:單調隊列。

dui[]表示單調隊列,t為隊頭,w為隊尾。

1、循環,若g(dui[t+1],dui[t])<p[i],說明dui[t+1]這個決策對于i來說要比dui[t]優,又因為p[i]是嚴格單調上升的,所以dui[t]這個決策對于后面的所有狀態均不產生影響,因此可以將dui[t]彈出單調隊列。循環結束后,可根據dui[t]算得f[i]。

2、循環,若g(i,dui[w])<g(dui[w],dui[w-1]):

1)若g(i,dui[w])<g(dui[w],dui[w-1])<p[i],可得g(i,dui[w])<p[i],所以決策i要優于決策dui[w],所以dui[w]這個決策對于后面的所有狀態均不產生影響,因此可以將dui[w]彈出單調隊列。

2)若p[i]<g(i,dui[w])<g(dui[w],dui[w-1]),可得決策dui[w]優于決策i,決策dui[w-1]優于決策dui[w],所以dui[w]這個決策對于后面的所有狀態同樣均不產生影響,因此可以將dui[w]彈出單調隊列。

綜上所述,首先求出斜率g(j,k),然后維護單調隊列,依次算出f[],答案即為f[n]。

附上AC代碼:

#include <cstdio>using namespace std; long long n,m,a[50010],s[50010],f[50010],p[50010],dui[50010],t,w; long long min(long long a,long long b){    return a<b?a:b;} long long calc(int x,int y){    return (f[x]+(p[x]+m)*(p[x]+m)-f[y]-(p[y]+m)*(p[y]+m))/(2*(p[x]-p[y]));} int main(void){    scanf("%lld%lld",&n,&m);++m;    for (int i=1; i<=n; ++i)        scanf("%lld",&a[i]),s[i]=s[i-1]+a[i],p[i]=s[i]+i;    dui[t=w=1]=0;    for (int i=1; i<=n; ++i){        while (t<w&&calc(dui[t+1],dui[t])<=p[i]) ++t;        int k=dui[t];        f[i]=f[k]+(p[i]-p[k]-m)*(p[i]-p[k]-m);        while (t<w&&calc(i,dui[w])<calc(dui[w],dui[w-1])) --w;        dui[++w]=i;    }    PRintf("%lld",f[n]);    return 0;}寫在最后:雖說這題是斜率優化的入門題,但是要真正弄明白也是不容易的。希望讀者們能多加思考,并AC這題。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 灵川县| 合川市| 新乡县| 惠安县| 灵寿县| 渭源县| 无为县| 隆子县| 靖边县| 原阳县| 寿阳县| 霍林郭勒市| 仙桃市| 龙州县| 灵台县| 和林格尔县| 慈利县| 绩溪县| 左权县| 松原市| 万宁市| 临颍县| 边坝县| 如东县| 武威市| 五台县| 汝南县| 勐海县| 梁山县| 桓仁| 乌兰察布市| 登封市| 赤城县| 娄烦县| 阳春市| 谢通门县| 平顺县| 甘德县| 河北省| 安福县| 土默特左旗|