标签:bzoj usaco2008 动态规划 斜率优化 dp
题目大意:给出一些木板,现在要购买这些木板。购买的规则是可以一些木板一起买,然后价格是最大的长度乘最大的宽度。求购买所有木板的最小费用。
思路:如果一个木板的长也比一个木板小,宽也比一个木板小,那么这个木板就可以被排除。把所有木板按照x的长度排序,然后去掉排除的木板,然后剩下的木板就是x值下降, y值上升的木板。这样的话我们买下连续的一段的费用就是x[j] * y[i],然后DP方程就很简单了:f[i] = f[j] - x[j + 1] * y[i]。
注意到数据范围,写一个斜率优化就水过了。
CODE:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 50010 using namespace std; struct Complex{ int x,y; bool blocked; bool operator <(const Complex &a)const { return x > a.x; } void Read() { scanf("%d%d",&x,&y); } }src[MAX],point[MAX]; struct Point{ long long x,y; Point(long long _ = 0,long long __ = 0):x(_),y(__) {} }q[MAX]; int cnt,total; long long f[MAX]; int front,tail; inline double GetSlope(const Point &a,const Point &b) { if(a.x == b.x) return 1e15; return (double)(a.y - b.y) / (a.x - b.x); } inline void Insert(long long x,long long y) { Point now(x,y); while(tail - front >= 2) if(GetSlope(q[tail],now) < GetSlope(q[tail - 1],q[tail])) --tail; else break; q[++tail] = now; } inline Point GetAns(double slope) { while(tail - front >= 2) if(GetSlope(q[front + 1],q[front + 2]) < slope) ++front; else break; return q[front + 1]; } int main() { cin >> cnt; for(int i = 1; i <= cnt; ++i) src[i].Read(); sort(src + 1,src + cnt + 1); int now = 0; for(int i = 1; i <= cnt; ++i) { if(src[i].y <= now) src[i].blocked = true; else now = src[i].y; } for(int i = 1; i <= cnt; ++i) if(!src[i].blocked) point[++total] = src[i]; for(int i = 1; i <= total; ++i) { Insert(-point[i].x,f[i - 1]); Point ans = GetAns(point[i].y); f[i] = ans.y - point[i].y * ans.x; } cout << f[total] << endl; return 0; }
BZOJ 1597 Usaco 2008 Mar 土地购买 斜率优化DP
标签:bzoj usaco2008 动态规划 斜率优化 dp
原文地址:http://blog.csdn.net/jiangyuze831/article/details/41674789