很早就知道了这题可以三分,但当时我听到的说法是三分套三分,就退缩了- -。
今天理解了一下某位神牛的代码,写的很巧妙,也挺好懂的。要注意需要判断三分出来的两个点是否重合,如果重合的话要选择左边一个点。
代码:
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
const double eps = 1e-12;
struct Point
{
double x,y;
Point(double u = 0,double v = 0){x = u;y = v;}
Point operator +(const Point &A){return Point(x + A.x,y + A.y);}
Point operator -(const Point &A){return Point(x - A.x,y - A.y);}
Point operator /(const double &A){return Point(x / A,y / A);}
};
Point a[2],b[2],P[2];
double p,q,r;
double sqr(double x){return x * x;}
void read(Point &A){scanf("%lf%lf",&A.x,&A.y);}
void init()
{
freopen("bzoj1857.in","r",stdin);
freopen("bzoj1857.out","w",stdout);
}
void readdata()
{
for(int i = 0;i < 2;i++)
{
read(a[i]);read(b[i]);
}
scanf("%lf%lf%lf",&p,&q,&r);
}
double dist(Point A,Point B)
{
return sqrt(sqr(B.x - A.x) + sqr(B.y - A.y));
}
double getA()
{
return dist(a[0],P[0]) / p + dist(P[0],P[1]) / r + dist(P[1],b[1]) / q;
}
double divide3(int k)
{
Point L = a[k],R = b[k],M1,M2,del;
double A1,A2;
while(dist(L,R) > eps)
{
del = (R - L) / 3;
M1 = L + del;M2 = R - del;
P[k] = M1;
if(k)A1 = divide3(1 - k); else A1 = getA();
P[k] = M2;
if(k)A2 = divide3(1 - k); else A2 = getA();
if(A1 < A2)R = M2;else L = M1;
}
if(dist(a[k],b[k]) <= eps)
{
P[k] = a[k];
if(k)return divide3(1 - k);
else return getA();
}
return A1;
}
void solve()
{
double ans = divide3(1);
printf("%.2lf\n",ans);
}
int main()
{
init();
readdata();
solve();
return 0;
}