Description
小A有一个游戏,这个游戏中的某个城市的地图是一个大型方格网,左下角为(-109,-109),右上角为(109,109)。在方格网内部(包括边界)每个整点都是一个路口,每条直线x=x0或y=y0(x0, y0为整数)在方格网内部(包括边界)的部分都是该城市的一条街道。此外,该城市还存在一条斜向的街道,其直线方程为Ax+By+C=0(A, B均不等于0),这条斜向的街道与方格网的交叉点也是路口。现在有N个人,所有人都只能沿着城市的街道行走,其中第i个人要从该城市的路口(ai,bi)走到路口(ci,di)。小A希望计算每个人需要走的最短路径的长度。由于N太大了,小A不想自己算,因此他向你求助。
Input
第一行,四个整数N, A, B, C。
接下来的N行,每行四个整数ai, bi, ci, di。
Output
N行,每行一个实数(保留3位小数),其中第i行的整数表示第i个人需要走的最短路径的长度。
Data Constraint
对于30%的数据,|A|,|B|,|C|,|ai|,|bi|,|ci|,|di|<=10;
对于全部的数据,|A|,|B|,|C|,|ai|,|bi|,|ci|,|di|<=10^9,1<=N<=2000
Analysis
如图所示,起点终点分别为点A、点
那么问题可以大致分成三步
- 从起点走向斜路
- 走一段斜路
- 从斜路走向终点
斜路的路径好求,勾股定理。走向斜线的距离也好求,即图中红色路径。显然走A−>B要比A−>C−>B短(面壁)
对于给定的Ax+By+C=0变形
x=−By−CA,y=−Ax−CB
就能愉悦简单地求出
卡精度都™去屎吧
一道水题写这么多作甚
Code
#include <stdio.h>
#include <math.h>
#define inf 0x7fffffff
using namespace std;
struct pos{long double x,y;}jd[5];
double min(long double x,long double y)
{
return x<y?x:y;
}
long double dis(pos a,pos b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
long double mht(pos a,pos b)
{
return fabs(a.x-b.x)+fabs(a.y-b.y);
}
int main()
{
long long a,b,c;
int n;
scanf("%d%lld%lld%lld",&n,&a,&b,&c);
for (int i=1;i<=n;i++)
{
pos st,ed;
long long x1,y1,x2,y2;
scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
st=(pos){x1,y1};
ed=(pos){x2,y2};
long double ans=mht(st,ed);
jd[1]=(pos){(-b*st.y-c)/(a*1.0),st.y};
jd[2]=(pos){st.x,(-a*st.x-c)/(b*1.0)};
jd[3]=(pos){(-b*ed.y-c)/(a*1.0),ed.y};
jd[4]=(pos){ed.x,(-a*ed.x-c)/(b*1.0)};
for (int i=1;i<4;i++)
for (int j=i+1;j<5;j++)
ans=min(ans,mht(st,jd[i])+mht(ed,jd[j])+dis(jd[i],jd[j]));
printf("%.3Lf\n",ans);
}
return 0;
}