1.hdu3507
裸題,有助於理解斜率優化的精髓。
dp[i]=min(dp[j]+m+(sum[i]-sum[j])2)
很顯然不是單調佇列。
根據斜率優化的的定義,就是先設兩個決策j,k
什麼時候我們認為在 i 的環境下 j 比 k 好呢?根據上面的遞推式,得到下面這麼乙個式子
dp[j]+m+(sum[i]-sum[j])2
2開啟括號:
dp[j]+m+sum[i]2+sum[j]2-2*sum[i]*sum[j]2+sum[k]2-2*sum[i]*sum[k]
移項,將有 i 的項移到右側:
dp[j]+sum[j]2-dp[k]-sum[k]2
<2*sum[i]*(sum[j]-sum[k])
除下來:
(dp[j]+sum[j]2-dp[k]-sum[k]2)/[2*(sum[j]-sum[k])]好了這就是斜率了^_^
1 #include2 #include3 #include4 typedef longlong
lnt;
5int q[1000000
];6 lnt sum[1000000
];7 lnt dp[1000000];8
inth,t;
9lnt n;
10lnt m;
11 lnt x(int
x)12
15 lnt tp(int i,int
j)16
19 lnt btm(int i,int
j)20
23int
main()
2444 printf("
%lld\n
",dp[n]);45}
46return0;
47 }
2.bzoj1010: [hnoi2008]玩具裝箱toy
這道題依然斜率單調
dp方程自己推:
dp[i]=min(dp[j]+(i-j-1+sum[i]-sum[j]-l)2)
依然假設在 i 的環境下決策 j 優於 k
那麼:dp[j]+(i-j-1+sum[i]-sum[j]-l)2
2將常數項與與 i 有關的項放到一起,展開:
(sum[j]+j)2-2*(i+sum[i]-l-1)*(sum[j]+j)+dp[j]<(sum[k]+k)2-2*(i+sum[i]-l-1)*(sum[k]+k)+dp[k]
設函式 f(x)=sum[x]+x , h(x)=x+sum[x]-l-1 , g(x)=dp[x]+f(x)2
得到當:
g(j)-g(k)<2*h(i)*(f(j)-f(k)) 時,j 比 k 優秀。
f(x)單調遞增,斜率單調。
時間複雜度o(n)
**:
1 #include2 #include3 #include4 typedef longlong
lnt;
5 lnt sum[1000000
];6 lnt dp[1000000];7
int q[1000000];8
inth,t;
9int
n;10
lnt l;
11 lnt f(int
x)12
15 lnt k(int
x)16
19 lnt g(int
x)20
23lnt squ(lnt x)
2427
intmain()
2835 q[1]=0
;36 dp[0]=0
;37 h=t=1;38
for(int i=1;i<=n;i++)
3947 printf("
%lld\n
",dp[n]);
48return0;
49 }
3.bzoj1911: [apio2010]特別行動隊
斜率單調。
方程自己推:
設:g(x)=a*x2+b*x+c
dp[i]=max(dp[j]+g(sum[i]-sum[j]))
設在 i 環境下決策 j 優於 k
dp[j]+g(sum[i]-sum[j])>dp[k]+g(sum[i]-sum[k])
設f(x)=dp[x]+a*sum[x]2-b*sum[x]
則當:f(j)-f(k)>2*a*sum[i]*(sum[j]-sum[k])
設 j > k 斜率單調
時間複雜度o(n)
**:
1 #include2 #include3 #include4 typedef longlong
lnt;
5 lnt sum[1000006
];6 lnt dp[1000006];7
int q[1000006];8
inth,t;
9int
n;10
lnt a,b,c;
11 lnt f(int
x)12
15lnt g(lnt x)
1619
int main(void)20
30 q[1]=0
;31 dp[0]=0;32
for(int i=1;i<=n;i++)
3341 printf("
%lld\n
",dp[n]);
42return0;
43 }
4.bzoj4518: [sdoi2016]征途
這次變成二維的了。
都一樣,展開方程+斜率優化。
這次要對於每一天進行o(n)轉移,共m天,時間複雜度o(n*m)
**:
1 #include2 #include3 #include4 typedef longlong
lnt;
5 lnt dp[4000][4000
];6 lnt sum[10000];7
int q[1000000];8
lnt n,m;
9lnt l;
10int
h,t;
11lnt squ(lnt x)
1215 lnt f(int x,int
i)16
19int
main()
2027 l=sum[n];
28for(int i=1;i<=n;i++)
2932
for(int d=2;d<=m;d++)
3345
}46 printf("
%lld\n
",dp[n][m]+squ(l));
47return0;
48 }
斜率優化 DP
我們知道,有些dp方程可以轉化成dp i f j x i 的形式,其中f j 中儲存了只與j相關的量。這樣的dp方程我們可以用單調佇列進行優化,從而使得o n 2 的複雜度降到o n 可是並不是所有的方程都可以轉化成上面的形式,舉個例子 dp i dp j x i x j x i x j 如果把右邊...
dp斜率優化
我們知道,有些dp方程可以轉化成dp i f j x i 的形式,其中f j 中儲存了只與j相關的量。這樣的dp方程我們可以用單調佇列進行優化,從而使得o n 2 的複雜度降到o n 可是並不是所有的方程都可以轉化成上面的形式,舉個例子 dp i dp j x i x j x i x j 如果把右邊...
斜率優化DP
斜率優化主要解決的是轉移方程中存在乙個同時與i和j有關的部分時的優化問題 dp i min dp j a i b j 0 include using namespace std typedef long long ll const int maxn 1e5 5 ll a maxn b maxn dp...