您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: