[USACO08MAR]土地徵用Land Acquisition——[斜率優化DP]

在這裏插入圖片描述
在這裏插入圖片描述
【題意分析】

首先可以發現一個性質:如果一個矩形長和寬都小於等於另一個,完全可以過濾掉這個矩形。

怎麼實現?排個序就好了

然後我們dp[i]表示前i個矩形的最小費用,那麼

dpi=min1j<i{dpj+wj+1hi}dp_i=\min _{1\leq j<i}\{ dp_j+w_{j+1}h_i\}

斜率優化一下得到:

dpxdpywy+1wx+1<hi\frac {dp_x-dp_y}{w_{y+1}-w_{x+1}}<h_i

就好了

Code:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#define MAXN 100000
#define db double
#define int long long
using namespace std;

struct Node {
	int w, h;
}a[MAXN];

int dp[MAXN], q[MAXN], n, tot;

inline int read () {
	register int s = 0, w = 1; 
	register char ch = getchar ();
	while (! isdigit (ch)) {if (ch == '-') w = -1; ch = getchar ();}
	while (isdigit (ch)) {s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar ();}
	return s * w;
}

inline bool cmp (Node x, Node y) {return (x.w == y.w) ? x.h > y.h : x.w > y.w;}
inline db slope (int x, int y) {return 1.0 * (dp[x] - dp[y]) / (a[y + 1].w - a[x + 1].w);}

signed main () {
	n = read (); int tot = 0;
	for (register int i = 1; i <= n; i++) a[i].w = read (), a[i].h = read ();
	sort (a + 1, a + n + 1, cmp);
	for (register int i = 1; i <= n; i++) if (a[i].h > a[tot].h) a[++tot] = a[i];
	int h = 0, t = 0;
	for (register int i = 1; i <= tot; i++) {
		while (h < t && slope (q[h + 1], q[h]) < a[i].h) h++;
		dp[i] = dp[q[h]] + a[i].h * a[q[h] + 1].w;
		while (h < t && slope (q[t], q[t - 1]) > slope (i, q[t])) t--;
		q[++t] = i;
	}
	return printf ("%lld\n", dp[tot]), 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章