Luogu P2179 NOI2012 騎行川藏

2022-05-12 11:14:49 字數 2950 閱讀 4252

給定 \(n\) 個路段,每個路段用三個實數 \(s_i,k_i,v^\prime_i\) 描述,最小化

\[f(v_1,\cdots v_n)=\sum\limits_^\frac

\]其中 \(v_1,\cdots v_n\) 均為非負實數而且需要滿足

\[\varphi(v_1,\cdots,v_n)=\sum\limits_^k_i(v_i-v^_i)^2s_i-e_u=0

\]\(\texttt1\leq n\leq 1000\)

拉格朗日乘子法。

我們來形象的講一下這個東西到底是什麼,你可能需要一些關於多元函式微積分的知識。

假設我們現在有乙個二元函式 \(f(x,y)=x^2+y^2\),需要求這個東西的最小值。

如果沒有限制的話,最小值就是 \(0\)。但是我如果需要讓 \(x,y\) 滿足 \(x^2y=3\) 的話呢?

乙個很顯然的想法就是去逐一列舉乙個最小值 \(r\),然後看這個 \(r\) 滿不滿足條件。於是我們只需要看看 \(x^2y=3\) 和 \(x^2+y^2=r\) 是否相交。

注意到後者的影象是乙個圓,從小到大列舉 \(r\) 的過程可以看做是圓的半徑逐漸擴大。如果擴大到某個 \(r\) 剛好與 \(x^2y=3\) 相交了的話就可以取這個 \(r\) 作為最小值。

這裡有乙個 demo,拖動 \(r_0\) 的滑動條相當於是圓的半徑逐漸擴大。注意到隨著半徑的擴大,圓與曲線的位置關係是先相離再相切最後相交。所以說,在極值點,圓與曲線相切

注意到這些圓是可以看做 \(f(x,y)=x^2+y^2\) 的等高線的。注意到 \(\nabla f\)(也就是梯度)是等高線的法線。同時 另乙個函式 \(g(x,y)=x^2y\) 的梯度向量 \(\nabla g\) 也會垂直於 \(x^2y=3\) 這條等高線。

因為梯度向量是等高線的法線,所以梯度與等高線的切線垂直。結合兩個加粗的條件我們可以知道在相切點,圓的梯度向量和曲線的梯度向量平行。這個時候我們可以列方程了:

\[\nabla f=\lambda\nabla g

\]也就是說

\[\begin\frac=\lambda\frac\\\frac=\lambda\frac\\x^2y=3\end

\]解出來即可。

這個時候我們可以考慮構造約束函式 \(\varphi(x,y)=x^2y-3\)。由於 \(3\) 是常數在對任何乙個變數求偏導數的時候都會消去所以不會對上面兩個方程產生影響。

由於偏導數的可加性,我們增加乙個新的變數 \(\lambda\) 並且將原來的函式寫成這樣:(也就是將等式的右邊移到了左邊)

\[f(x,y,\lambda)=f(x,y)+\lambda\varphi(x,y)

\]這個時候很容易看出對 \(f(x,y,\lambda)\) 求三個偏導數得到的方程與上面的方程組是一樣的。

對於這個題目來說,建構函式

\[f(v_1,\cdots,v_n,\lambda)=f(v_1,\cdots,v_n)+\lambda\varphi(v_1,\cdots,v_n)=\sum\limits_^\frac+\lambda\left(\sum\limits_^k_i(v_i-v^_i)^2s_i-e_u\right)

\]根據對稱性我們可以很方便的求出這個東西對 \(v_i\) 和 \(\lambda\) 的偏導數:

\[\frac=2\lambda k_i(v_i-v^\prime_i)s_i-\frac

\]\[\frac=\sum\limits_^k_i(v_i-v^\prime_i)^2s_i-e_u

\]按照上面講的東西,這些偏導數都應該等於 \(0\) 的,所以得到兩個方程:

\[2\lambda k_iv_i^2(v_i-v^\prime_i)=1

\]\[\sum k_i(v_i-v^)^2s_i=e_u

\]將第乙個方程移項得到

\[v_i^2(v_i-v^\prime_i)=\frac

\]左邊那個東西當 \(v_i\in [0,+\infty)\) 的時候通過對導數進行分析可以看出是單調遞增的。

當 \(\lambda\) 固定的時候,\(v_i\uparrow\) 則等式左邊 \(\uparrow\)。當 \(\lambda\uparrow\) 時,因為等式右邊 \(\downarrow\),所以 \(v_i\downarrow\)。因為 \(v_i>v^\prime_i\),所以第二個等式的左邊整體是 \(\downarrow\) 的。

於是我們可以考慮二分 \(\lambda\),然後二分解出 \(v_i\) 利用第二個等式再 check 即可。

#includeusing namespace std;

typedef int ll;

typedef long long int li;

typedef long double db;

const ll maxn=2e5+51;

const db eps=1e-12;

ll n;

db eu,l,r,mid,res;

db s[maxn],kk[maxn],v[maxn],vl[maxn];

inline ll read()

if(ch=='-')

while(isdigit(ch))

return num*neg;

}#define sqr(x) (x)*(x)

inline db calcderiv(db lambda,db vel,ll x)

inline ll check(db lambda)

vl[i]=l,e+=kk[i]*sqr(vl[i]-v[i])*s[i];

}return e<=eu;

}int main()

while(l+eps<=r)

for(register int i=1;i<=n;i++)

printf("%.9lf\n",res);

}

LG P2179 NOI2012 騎行川藏

蛋蛋非常熱衷於挑戰自我,今年暑假他準備沿川藏線騎著自行車從成都前往拉薩.川藏線的沿途有著非常美麗的風景,但在這一路上也有著很多的艱難險阻,路況變化多端,而蛋蛋的體力十分有限,因此在每天的騎行前設定好目的地,同時合理分配好自己的體力是一件非常重要的事情.由於蛋蛋裝備了一輛非常好的自行車,因此在騎行過程...

luoguP2254 NOI2005 瑰麗華爾茲

題目比較好,人比較菜。include define maxn 205 using namespace std int n,m,x,y,k,f maxn maxn maxn l,r,d,dx 7 dy 7 l,r,q maxn ans 0 char tu maxn maxn int main mems...

luogu P2387 NOI2014 魔法森林

傳送門 這題似乎不好直接做,可以考慮按照 a i 公升序排序,然後依次加邊更新答案 具體實現方法是用lct維護當前的樹,這裡需要維護鏈上最大的 b i 每次加一條邊,如果加完以後沒有環直接加,否則找出鏈上最大的 b i 如果這個 b i 比當前的 b i 小,加了肯定不優,否則就把那條邊斷掉,加上這...