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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

浅谈斜率优化dp

發(fā)布時(shí)間:2024/3/12 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浅谈斜率优化dp 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Ⅰ、前置知識(shí)

\(y=kx+b\)
\(k\)叫斜率,\(b\)叫截距
\((x_1,y_1)\)\((x_2,y_2)\)兩點(diǎn)連成的直線的斜率\(k=\frac{y1-y2}{x1-x2}\)

Ⅱ、拋出問題

洛谷板子

題目描述

\(n\)個(gè)任務(wù)排成一個(gè)序列在一臺(tái)機(jī)器上等待完成(順序不得改變),這\(n\)個(gè)任務(wù)被分成若干批,每批包含相鄰的若干任務(wù)。從時(shí)刻\(0\)開始,這些任務(wù)被分批加工,第\(i\)個(gè)任務(wù)單獨(dú)完成所需的時(shí)間是\(T_i\)。在每批任務(wù)開始前,機(jī)器需要啟動(dòng)時(shí)間\(S\),而完成這批任務(wù)所需的時(shí)間是各個(gè)任務(wù)需要時(shí)間的總和(同一批任務(wù)將在同一時(shí)刻完成)。每個(gè)任務(wù)的費(fèi)用是它的完成時(shí)刻乘以一個(gè)費(fèi)用系數(shù)\(F_i\)。請(qǐng)確定一個(gè)分組方案,使得總費(fèi)用最小。
例如:\(S=1\)\(T=\{1,3,4,2,1\}\)\(F=\{3,2,3,3,4\}\)。如果分組方案是\(\{1,2\}\)、\(\{3\}\)、\(\{4,5\}\),則完成時(shí)間分別為\(\{5,5,10,14,14\}\),費(fèi)用\(C=\{15,10,30,42,56\}\),總費(fèi)用就是\(153\)。

輸入輸出格式

輸入格式:

第一行是\(n(1\leq n\leq5000)\)。
第二行是\(S(0\leq S\leq50)\)。
下面\(n\)行每行有一對(duì)數(shù),分別為\(T_i\)\(F_i\),均為不大于\(100\)的正整數(shù),表示第\(i\)個(gè)任務(wù)單獨(dú)完成所需的時(shí)間是\(T_i\)及其費(fèi)用系數(shù)\(F_i\)。

輸出格式:

一個(gè)數(shù),最小的總費(fèi)用。

輸入輸出樣例

輸入樣例#1:

5
1
1 3
3 2
4 3
2 3
1 4

輸出樣例#1:

153

Ⅲ、分析問題

首先這題\(O(n^2)\)可以艸過
但是\(O(n^2)\)過了這題講斜率優(yōu)化毫無意義QAQ
所以請(qǐng)自動(dòng)將數(shù)據(jù)范圍改成\((1\leq n\leq500000)\)


先來看一眼普通\(dp\)\(O(n^2)\)怎么寫
設(shè)
\(f[i]\)表示處理到第\(i\)個(gè)任務(wù),前\(i\)個(gè)的最小費(fèi)用
\(t_i\)表示時(shí)間的前綴和
\(c_i\)表示費(fèi)用的前綴和
考慮從\(j\)轉(zhuǎn)移到\(i\),表示\(j+1\)\(i\)打包到一批
則狀態(tài)轉(zhuǎn)移方程為
\[f[i]=\min_{j=1}^{i}\{f[j]+s\times(c_n-c_j)+t_i\times(c_i-c_j)\}\]
由于之前哪些任務(wù)被分成一批不好處理,所以可以直接加上\(s\times(c_n-c_j)\)當(dāng)作對(duì)后續(xù)狀態(tài)的處理
然后推式子
\(j\)看作一個(gè)變量,然后去掉\(\min\),得到
\[f[i]=f[j]+s\times(c_n-c_j)+t_i\times(c_i-c_j)\]
拆括號(hào)
\[f[i]=f[j]+s\times c_n-s\times c_j+t_i\times c_i-t_i\times c_j\]
移項(xiàng)
\[f[i]-s\times c_n+s\times c_j-t_i\times c_i+t_i\times c_j=f[j]\]
\[f[j]=f[i]-s\times c_n+s\times c_j-t_i\times c_i+t_i\times c_j\]
提取公因式
\[f[j]=c_j\times(s+t_i)+f[i]-s\times c_n+-t_i\times c_i\]
此時(shí)式子推成這樣
再看一眼前置知識(shí)
\(y=kx+b?\)
此時(shí)我們的式子就像一條直線解析式!
\[x=c_j,y=f[j],k=s+t_i,b=f[i]-s\times c_n+-t_i\times c_i\]
我們想要最小化\(f[i]\),就是最小化\(b\)
而我們此時(shí)要做的,就是用一條已知斜率的直線,利用已有的坐標(biāo),找到一個(gè)最小的\(b\)
如圖,現(xiàn)在處理到\(i\),則共有\(i-1\)個(gè)坐標(biāo)為\((z_j,f[j])(1\leq j<i)\)的點(diǎn)
如圖所示

右下角為當(dāng)前處理的斜率為\(s+t_i\)的直線,我們要將它向上平移,直到和上方\(i-1\)個(gè)點(diǎn)中的一個(gè)相交
顯然要找的點(diǎn)\(j\)(也叫決策點(diǎn))一定在圖形的凸包上
又很顯然,決策點(diǎn)一定在下凸殼上,因?yàn)橄峦箽ど系狞c(diǎn)顯然比上凸殼更優(yōu)
又很顯然,決策點(diǎn)一定在下凸殼的右半側(cè),因?yàn)?span id="ozvdkddzhkzd" class="math inline">\(k\)(即\(s+t_i\))一定大于\(0\)
叕很顯然找到?jīng)Q策點(diǎn)之后是這樣的

如何找到?jīng)Q策點(diǎn)?
觀察可以知道,凸包上的直線的斜率具有單調(diào)性
二分!
每次二分一個(gè)點(diǎn),\(check\)這個(gè)點(diǎn)左側(cè)的直線的斜率是否小于\(s+t_i\),右側(cè)的斜率是否大于\(s+t_i\),如果是就證明找到了決策點(diǎn)
手玩一下更好理解
找到?jīng)Q策點(diǎn)之后,很明顯,決策點(diǎn)左邊所有的直線的截距都要大于\(s+t_i\),所以左邊的所有點(diǎn)都沒有當(dāng)前點(diǎn)優(yōu)
于是拿單調(diào)隊(duì)列存一下凸包是上的點(diǎn),如果沒有當(dāng)前直線優(yōu)則踢掉
找到?jīng)Q策點(diǎn)后,相當(dāng)于找到了\(j\),更新\(f[i]\)
更新完\(f[i]\)后,為了方便后續(xù)的查找,將\((c_i,f[i])\)插入凸包,并且維護(hù)一下凸包的單調(diào)性
最后輸出\(f[n]\)即可
代碼:

#include<bits/stdc++.h> #define F(i,j,n) for(register int i=j;i<=n;i++) #define INF 0x3f3f3f3f #define ll long long #define mem(i,j) memset(i,j,sizeof(i)) using namespace std; int n,s,c[5010],t[5010],f[5010],q[5010],l,r; inline int read(){int datta=0;char chchc=getchar();bool okoko=0;while(chchc<'0'||chchc>'9'){if(chchc=='-')okoko=1;chchc=getchar();}while(chchc>='0'&&chchc<='9'){datta=datta*10+chchc-'0';chchc=getchar();}return okoko?-datta:datta; } int main(){n=read();s=read();F(i,1,n){t[i]=t[i-1]+read();c[i]=c[i-1]+read();}mem(f,0x3f);f[0]=0;l=1;r=0;q[++r]=0;F(i,1,n){while(l<r&&f[q[l+1]]-f[q[l]]<=(s+t[i])*(c[q[l+1]]-c[q[l]]))//避免精度誤差l++;//由于博主太菜了所以用的是線性而不是二分f[i]=f[q[l]]+s*(c[n]-c[q[l]])+t[i]*(c[i]-c[q[l]]);//更新while(l<r&&(f[i]-f[q[r]])*(c[q[r]]-c[q[r-1]])<=(f[q[r]]-f[q[r-1]])*(c[i]-c[q[r]]))r--;q[++r]=i;}printf("%d\n",f[n]);return 0; }

轉(zhuǎn)載于:https://www.cnblogs.com/hzf29721/p/10423775.html

總結(jié)

以上是生活随笔為你收集整理的浅谈斜率优化dp的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。