当火车处在换基站的临界点时,它到某两基站的距离相等。因此换基站的位置一定在某两个基站的中垂线上,

我们预处理出任意两基站之间的中垂线,对于每次询问,求询问线段与所有中垂线的交点。

检验这些交点是否满足条件(详见代码),如果满足,那么它是一个交换点。

#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm> using namespace std; const int MAXN = ; const double eps = 1e-; struct Point
{
double x, y;
Point( double x = , double y = ):x(x), y(y) { }
}; typedef Point Vector; struct Line
{
Point s;
Vector v;
Line( Point s = Point(), Point v = Point() ):
s(s), v(v) { }
}; int dcmp( double x ) //控制精度
{
if ( fabs(x) < eps ) return ;
else return x < ? - : ;
} Vector operator+( Vector A, Vector B ) //向量加
{
return Vector( A.x + B.x, A.y + B.y );
} Vector operator-( Vector A, Vector B ) //向量减
{
return Vector( A.x - B.x, A.y - B.y );
} Vector operator*( Vector A, double p ) //向量数乘
{
return Vector( A.x * p, A.y * p );
} Vector operator/( Vector A, double p ) //向量数除
{
return Vector( A.x / p, A.y / p );
} bool operator<( const Point& A, const Point& B ) //两点比较
{
return dcmp( A.x - B.x ) < || ( dcmp( A.x - B.x ) == && dcmp( A.y - B.y ) < );
} bool operator==( const Point& a, const Point& b ) //两点相等
{
return dcmp( a.x - b.x ) == && dcmp( a.y - b.y ) == ;
} double Dot( Vector A, Vector B ) //向量点乘
{
return A.x * B.x + A.y * B.y;
} double Length( Vector A ) //向量模
{
return sqrt( Dot( A, A ) );
} double Angle( Vector A, Vector B ) //向量夹角
{
return acos( Dot(A, B) / Length(A) / Length(B) );
} double Cross( Vector A, Vector B ) //向量叉积
{
return A.x * B.y - A.y * B.x;
} double Area2( Point A, Point B, Point C ) //向量有向面积
{
return Cross( B - A, C - A );
} Vector Rotate( Vector A, double rad ) //向量旋转
{
return Vector( A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad) );
} Vector Normal( Vector A ) //向量单位法向量
{
double L = Length(A);
return Vector( -A.y / L, A.x / L );
} Point GetLineIntersection( Point P, Vector v, Point Q, Vector w ) //两直线交点
{
Vector u = P - Q;
double t = Cross( w, u ) / Cross( v, w );
return P + v * t;
} double DistanceToLine( Point P, Point A, Point B ) //点到直线的距离
{
Vector v1 = B - A, v2 = P - A;
return fabs( Cross( v1, v2 ) ) / Length(v1);
} double DistanceToSegment( Point P, Point A, Point B ) //点到线段的距离
{
if ( A == B ) return Length( P - A );
Vector v1 = B - A, v2 = P - A, v3 = P - B;
if ( dcmp( Dot(v1, v2) ) < ) return Length(v2);
else if ( dcmp( Dot(v1, v3) ) > ) return Length(v3);
else return fabs( Cross( v1, v2 ) ) / Length(v1);
} Point GetLineProjection( Point P, Point A, Point B ) // 点在直线上的投影
{
Vector v = B - A;
return A + v*( Dot(v, P - A) / Dot( v, v ) );
} bool SegmentProperIntersection( Point a1, Point a2, Point b1, Point b2 ) //线段相交,交点不在端点
{
double c1 = Cross( a2 - a1, b1 - a1 ), c2 = Cross( a2 - a1, b2 - a1 ),
c3 = Cross( b2 - b1, a1 - b1 ), c4 = Cross( b2 - b1, a2 - b1 );
return dcmp(c1)*dcmp(c2) < && dcmp(c3) * dcmp(c4) < ;
} bool OnSegment( Point p, Point a1, Point a2 ) //点在线段上,不包含端点
{
return dcmp( Cross(a1 - p, a2 - p) ) == && dcmp( Dot( a1 - p, a2 - p ) ) < ;
} /****************以上模板******************/ int N, M;
Point city[MAXN]; //城市
Point GSM[MAXN]; //基站
Line L[MAXN][MAXN]; //点[i][j]之间的中垂线 void init()
{
for ( int i = ; i <= M; ++i )
for ( int j = i + ; j <= M; ++j )
{
Point mid = Point( (GSM[i].x+GSM[j].x)/2.0, (GSM[i].y+GSM[j].y)/2.0 );
L[i][j] = Line( mid, Normal( GSM[j] - GSM[i] ) );
L[j][i] = L[i][j];
}
return;
} //判断交点是否在线段上
bool check( Point st, Point ed, Point cp )
{
return ( st < cp || st == cp ) && ( cp < ed || cp == ed );
} //假设我在此交点交换基站
//那么交点到形成 该中垂线的线段的其中一端点 的距离 L 应该是最小的
//判断是否有点到交点的距离小于L,如果有,则不是在这一点交换的基站
bool check2( double limit, Point jiao )
{
for ( int i = ; i <= M; ++i )
{
double dis = Length( GSM[i] - jiao );
if ( dcmp( dis - limit ) < ) return false;
}
return true;
} int main()
{
//freopen( "in.txt", "r", stdin );
//freopen( "s.txt", "w", stdout );
while ( ~scanf( "%d%d", &N, &M ) )
{
for ( int i = ; i <= N; ++i )
scanf( "%lf%lf", &city[i].x, &city[i].y ); for ( int i = ; i <= M; ++i )
scanf( "%lf%lf", &GSM[i].x, &GSM[i].y ); init(); //初始化所有中垂线
int Q;
scanf( "%d", &Q );
while ( Q-- )
{
int a, b;
scanf( "%d%d", &a, &b );
if ( a > b ) swap( a, b );
Line train = Line( city[a], city[b] - city[a] ); //火车行进路线
int huan = ; //换基站次数
for ( int i = ; i <= M; ++i )
for ( int j = i + ; j <= M; ++j )
{
if ( dcmp( Cross( train.v, L[i][j].v ) ) == ) //如果中垂线与火车行进路线平行
continue;
Point tmp = GetLineIntersection( train.s, train.v, L[i][j].s, L[i][j].v ); //求交点//交点到形成中垂线的线段的其中一个端点的距离
double limit = Length( GSM[i] - tmp );
Point st = city[a], ed = city[b];
if ( ed < st ) swap( st, ed ); if ( check( st, ed, tmp ) ) //如果在线段上
{
if ( check2( limit, tmp ) ) //如果确实在这点交换基站
++huan;
}
}
printf( "%d\n", huan );
}
}
return ;
}

HDU 4643 GSM 算术几何的更多相关文章

  1. hdu 4643 GSM 计算几何 - 点线关系

    /* hdu 4643 GSM 计算几何 - 点线关系 N个城市,任意两个城市之间都有沿他们之间直线的铁路 M个基站 问从城市A到城市B需要切换几次基站 当从基站a切换到基站b时,切换的地点就是ab的 ...

  2. HDU 4643 GSM (2013多校5 1001题 计算几何)

    GSM Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submiss ...

  3. hdu 4643 GSM(暴力)

    GSM Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submis ...

  4. HDU 4643 GSM 简单计算几何

    今天比赛的时候略坑, admin告诉我询问Q的个数不超过n^2, 赛后敲了个 O(Q*m^3)的复杂度,但这个复杂度常数比较低,可能在除以个小常数, 300ms过了,真心无语,数据应该水了吧,比赛的时 ...

  5. HDU 4643 GSM 暑期多校联合训练第五场 1001

    点击打开链接 我就不说官方题解有多坑了 V图那么高端的玩意儿 被精度坑粗翔了 AC前 AC后 简直不敢相信 只能怪自己没注意题目For the distance d1 and d2, if fabs( ...

  6. hdu 4643(计算几何)

    题意:容易理解 分析:切换的地点为两个基站所在直线的中垂线与两座城市所在直线的交点. 代码实现: #include <cstdio> #include <cmath> #inc ...

  7. hdu 5605 geometry(几何,数学)

    Problem Description There is a point P at coordinate (x,y). A line goes through the point, and inter ...

  8. MT【23】用算术几何不等式证明数列极限存在

    评:如果不需要精确到3,上界的求法可以利用$$(1+\frac{1}{n})^n*\frac{1}{2}*\frac{1}{2}<(\frac{n+\frac{1}{n}*n+\frac{1}{ ...

  9. hdu 6097 Mindis(数学几何,圆心的反演点)

    Mindis Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Subm ...

随机推荐

  1. C语言函数指针基础

    本文写的非常详细,因为我想为初学者建立一个意识模型,来帮助他们理解函数指针的语法和基础.如果你不讨厌事无巨细,请尽情阅读吧. 函数指针虽然在语法上让人有些迷惑,但不失为一种有趣而强大的工具.本文将从C ...

  2. 深入理解jQuery中live与bind方法的区别

    本篇文章主要是对jQuery中live与bind方法的区别进行了详细的分析介绍,需要的朋友可以过来参考下,希望对大家有所帮助 注意如果是通过jq添加的层和对象一定要用live(),用其他的都不起作用 ...

  3. Ajax HTML, JS

    Ajax Request HTML <script></script>及外部的js文件,都需要 var scriptStrs = response.match(/\<[\ ...

  4. Linux的别名使用

    直接定义别名 编辑当前用户下的.bashrc 文件: vim  ~/.bashrc 添加别名为 lmysql 的命令语句 : alias lmysql='mysql -uroot -p -Dtest ...

  5. Javascript offsetLeft详情

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  6. OPEN资讯

    http://www.open-open.com/news/view/1f55540 随着 Android 平台市场份额的持续猛增 , 越来越多的开发者开始投入 Android 应用程序的开发大潮.如 ...

  7. House Robber II

    https://leetcode.com/problems/house-robber-ii/ Note: This is an extension of House Robber. After rob ...

  8. WCF分布式开发步步为赢(6):WCF服务契约继承与分解设计

    上一节我们学习了WCF分布式开发步步为赢(5)服务契约与操作重载部分.今天我们来继续学习WCF服务契约继承和服务分解设计相关的知识点.WCF服务契约继承有何优势和缺点?实际项目里契约设计有什么原则和依 ...

  9. 妙味课堂——HTML+CSS(第三课)

    常见标签我已经在上一篇文章中提及,我们做前端设计时,主要也是用这些标签(最常用的). 然而有一个问题,就是有的标签都有自己的默认样式.试通过如下代码来说明: <!DOCTYPE html> ...

  10. 如何在jmeter中调用自己写的java工具包

    本文介绍在jmeter中调用自己写java工具包,并非直接继承jmeter提供的java sample request接口. 工具/原料 jmeter eclipse 方法/步骤 通常用jmeter做 ...