1. 程式人生 > 其它 >模擬費用流學習筆記

模擬費用流學習筆記

基本問題

一個數軸上有 \(n\) 只老鼠和 \(m\) 個老鼠洞,第 \(i\) 只老鼠的座標為 \(x_i\),第 \(j\) 個老鼠洞的座標為 \(y_i\)

尋找一組匹配 \(S=\{(a,b)\mid a\in{\rm mouse},b\in{\rm hole}\}\)

Problem 1

每隻老鼠只能向左走。

\(i\) 只老鼠進第 \(j\) 個洞的代價為 \(x_i-y_j\),求所有老鼠進洞最小代價。

顯然貪心。

考慮 DP。先把老鼠和洞看成一樣的東西,將其首先按照座標排序,設計狀態 \(f_{i,j}\) 表示從左往右前 \(i\) 個“東西”中,有 \(j\)

個洞選中且還沒匹配上。轉移時分兩種情況:老鼠、洞。

如果當前是老鼠:

\[f_{i,j}=f_{i-1,j+1}+x_i \]

如果當前是洞:

\[f_{i,j}=\min\{f_{i-1,j-1}-y_i,f_{i-1,j}\} \]

由於下標遞增,發現 \(f_{i-1,j-1}-y_i\le f_{i-1,j}\),所以直接選擇前面的決策。

發現每次轉移相當於整體向左/右平移一格、全域性加。這裡我們只需要維護 \(f_{i,0}\) 和差分陣列 \(d_{i,j}=f_{i,j}-f_{i,j-1}\),由於每次相當於在開頭加入/刪除一個元素,使用 即可。複雜度 \(\mathcal O({\rm sort}(n))+\mathcal O(n)\)

int f0 = 0;
stack<int> Q;
for (int i = 1; i <= n; i++)
	if (op[i] == 1) // 老鼠
		f0 += a[i] + Q.top(), Q.pop();
	else // 洞
		Q.push(-a[i]);

之後維護的思路與此十分相似。該維護方式之後將具有非常大的優勢。

Problem 2

(to be continue..)