D. Barcelonian Distance
题意
给你一条二维平面上的直线,给你两个点,问从A点走到B点的最短路径
点只能在给定直线和与坐标轴平行的直线上行走。
做法
如果不经过直线,一定直接是曼哈顿距离
如果经过直线,一定是A沿直线走到直线上最优,从直线上延直线走到B最优
而从A直接走到给定直线有两种走法,从给定直线走到B有两种走法
所以只要判断上述5种走法的最小值即可。
坑点
给定直线斜率为0时注意要特判,斜率为0或者inf,那么就是曼哈顿距离
代码
#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e5+5;
double dis(double a,double b,double c,double d)
{
return sqrt((a-c)*(a-c)+(b-d)*(b-d));
}
int main()
{
ll a,b,c,x_1,y_1,x_2,y_2;
scanf("%lld%lld%lld",&a,&b,&c);
scanf("%lld%lld%lld%lld",&x_1,&y_1,&x_2,&y_2);
double ans,ans1,xx1,yy1,xx2,yy2;
//曼哈顿距离
ans=1.0*(abs(x_2-x_1)+abs(y_2-y_1));
//x 1 y 1
ans1=0;
xx1=1.0*x_1;
yy1=-1.0*(1.0*a*x_1+c)*(1.0/b);
xx2=1.0*x_2;
yy2=-1.0*(1.0*a*x_2+c)*(1.0/b);
ans1+=fabs(yy1-y_1)+fabs(yy2-y_2);
ans1+=dis(xx1,yy1,xx2,yy2);
ans=min(ans,ans1);
//x 1 y 0
ans1=0;
xx1=1.0*x_1;
yy1=-1.0*(1.0*a*x_1+c)*(1.0/b);
xx2=-1.0*(1.0*b*y_2+c)*(1.0/a);
yy2=1.0*y_2;
ans1+=fabs(yy1-y_1)+fabs(xx2-x_2);
ans1+=dis(xx1,yy1,xx2,yy2);
ans=min(ans,ans1);
//x 0 y 0
ans1=0;
xx1=-1.0*(1.0*b*y_1+c)*(1.0/a);
yy1=1.0*y_1;
xx2=-1.0*(1.0*b*y_2+c)*(1.0/a);
yy2=1.0*y_2;
ans1+=fabs(xx1-x_1)+fabs(xx2-x_2);
ans1+=dis(xx1,yy1,xx2,yy2);
ans=min(ans,ans1);
//x 0 y 1
ans1=0;
xx1=-1.0*(1.0*b*y_1+c)*(1.0/a);
yy1=1.0*y_1;
xx2=1.0*x_2;
yy2=-1.0*(1.0*a*x_2+c)*(1.0/b);
ans1+=fabs(xx1-x_1)+fabs(yy2-y_2);
ans1+=dis(xx1,yy1,xx2,yy2);
ans=min(ans,ans1);
printf("%.10f\n",ans);
return 0;
}