HDU 4128 Running relay (贪心+凸包优化)
2013-11-11 01:05
423 查看
题解
一个很容易YY的结论:最多只有两个人跑,难在证明。题解中的x+y=1,x*sa+y*sc=sb这两个等式太犀利了。然后就是解方程组:
li + lj = L
li*si + lj*sj = W
ans = li*Ti + lj*Tj
li表示i跑的距离。
解出ans的表达式后可以转化成点斜式的方程,求出凸包后3分求解。
/* Created Time: Sunday, November 10, 2013 PM11:34:14 CST */ #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int N = 10007; const double eps = 1e-6; int n,d; double L,W; inline int sig(double x) { return (x>eps)-(x<-eps); } // Si:x , Ti:y struct point { double x,y; point(int _x=0,int _y=0) : x(_x),y(_y) {} bool operator < (const point &tt) const { return sig(x-tt.x)<0 || sig(x-tt.x)==0 && sig(y-tt.y)<0; } point operator - (const point &tt) const { return point(x-tt.x,y-tt.y); } }dot ,con ; inline double cross(point a,point b) { return a.x*b.y-a.y*b.x; } int set_convex(point *dot,int n) { int top = 0; if (n==0) return 0; con[top++] = dot[0]; if (n==1) return 1; con[top++] = dot[1]; for (int i = 2; i < n; i ++) { while (top>=2 && sig(cross(con[top-1]-con[top-2],dot[i]-con[top-2]))<=0) top --; con[top++] = dot[i]; } return top; } double ternary(point a,int l,int r) { double slop = 1e30; while (l<=r) { int lfd = (2*l+r)/3; int rfd = (l+2*r)/3; double ll = (a.y-con[lfd].y)/(a.x-con[lfd].x); double rr = (a.y-con[rfd].y)/(a.x-con[rfd].x); if (sig(ll-rr)>=0) { l = lfd+1; slop = min(slop,rr); } else { r = rfd-1; slop = min(slop,ll); } } return a.y*L+(W-a.x*L)*slop; } double work() { double ret = 1e30; if (sig(W)<0 || sig(L)<0) return -1; sort(dot,dot+n); int j = 1; for (int i = 0; i < n; i ++) { if (sig(dot[i].y-dot[j-1].y)>=0) continue; dot[j++] = dot[i]; } n = j; if (sig(W-L*dot[0].x)<0) return -1; if (n==1) return L*dot[0].y; for (j = 0; j<n && sig(W-L*dot[j].x)>=0; j ++); int tot = j; int sz = set_convex(dot+j,n-j); for (int i = 0; i < tot; i ++) { ret = min(ret,L*dot[i].y); ret = min(ret,ternary(dot[i],0,sz-1)); } return ret; } int main() { int cas; scanf("%d",&cas); while (cas--) { scanf("%d%d%lf%lf",&n,&d,&L,&W); double base = 0; for (int i = 0; i < n; i ++) { int a,b; scanf("%d%d",&a,&b); dot[i].x = a; dot[i].y = b; W -= dot[i].x*d; L -= d; base += dot[i].y*d; } double ans = work(); if (sig(ans)<0) puts("No solution"); else printf("%.2f\n",ans+base); } return 0; }
相关文章推荐
- Javascript null和undefined
- 用Python最原始的函数模拟eval函数的浮点数运算功能(2)
- count the occurences of anagrams
- HDU2196 - Computer(树形DP)
- 如何成为一个牛逼的C/C++程序员?
- fal 失败 无法读取丢失的日志
- 第三章 jQuery中的DOM操作
- 机器学习&数据挖掘笔记_16(常见面试之机器学习算法思想简单梳理)
- Cocos2d-x 2.x:CCTableView的使用
- p45-001
- Android实现导航菜单左右滑动效果
- 图纸网站整改意见.doc
- android多选联系人实现
- SmartUpload类实现上传和下载
- 茶盘网整改意见
- Concrete maths reading notes 1 - ch. 1&2
- c++中WaitForSingleObject函数解析
- myeclipse 遇到的一些问题及解决方案
- C++中const用法总结
- c# in depth之泛型的类型约束详细