# 【BZOJ1597】【Usaco2008 Mar】土地购买 斜率优化DP

## 思路与做法:

$f_i = min \{f_j + x_i * y_{j+1} \}$

$f_j + x_i * y_{j+1} < f_k + x_i * y_{k+1}$

$f_j - f_k < x_i*y_{k+1} - x_i*y_{j+1}$

${f_j - _k \over y_{k+1} - y_{j+1}} < x_i$

## 代码：

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

const int N = 50010;

struct Data
{   int x, y;
bool operator < (const Data &rhs) const { return x < rhs.x || (x == rhs.x && y < rhs.y); }
} a[N];
vector<int> x, y;

int Q[N], hd, tl;
long long f[N];
inline double calc(int j, int k) { return (double)(f[j]-f[k]) / (double)(y[k+1]-y[j+1]); }

int main()
{   int n;
scanf("%d", &n);
for(int i=1; i<=n; i++)
scanf("%d %d", &a[i].x, &a[i].y);
sort(a+1, a+1+n);
x.push_back(0);
y.push_back(0);
for(int i=1; i<=n; i++)
{   while(x.size() > 1 && y.size() > 1 && y.back() <= a[i].y)
x.pop_back(), y.pop_back();
x.push_back(a[i].x);
y.push_back(a[i].y);
}
Q[hd = 0] = 0;
tl = 1;
for(int i=1; i<x.size(); i++)
{   while(hd < tl-1 && calc(Q[hd+1], Q[hd]) <= x[i]) hd++;
f[i] = f[Q[hd]] + (long long)y[Q[hd]+1] * (long long)x[i];
while(hd < tl-1 && calc(i, Q[tl-1]) <= calc(Q[tl-1], Q[tl-2])) tl--;
Q[tl++] = i;
}
printf("%lld\n", f[x.size()-1]);
return 0;
}

posted @ 2018-03-18 20:19  EZ_WYC  阅读(93)  评论(0编辑  收藏  举报