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

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

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

#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. Gentoo 网络接口配置文件说明

    裁剪的Gentoo系统,仅供公司内部使用! [作为备份档案] 网络接口配置:/etc/conf.d/net #设置静态IPconfig_eth0="192.168.1.x/24" ...

  2. Angular 2 Quickstart

    写一个Angular 2的应用最基本的步骤概括为三步:写root组件,启动它(Boostrap),写index.html. 一些关于命名空间的基本知识 把所有代码放入一个立即调用函数中,通过传入一个空 ...

  3. 线段树--Color the ball(多次染色问题)

    K - Color the ball Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u ...

  4. 版本控制 - SVN/TortoiseSVN

    研读了blog: 1. http://www.open-open.com/lib/view/open1346982569725.html  2. http://www.360doc.com/conte ...

  5. [解决方案] 当 IDENTITY_INSERT 设置为 OFF 时

    当 IDENTITY_INSERT 设置为 OFF 时,不能为表 'tbUser' 中的标识列插入显式值. 解决:这个情况是你的表里面,有一列数据类型是IDENTITY的,也就是数据库自动递增列对于自 ...

  6. MAC下搭建web开发环境

    具体做法,参照此链接:http://mallinson.ca/osx-web-development/ Mac系统本身自带apache和PHP,MySQL可以安装也可以不安装 web开发的IDE可以是 ...

  7. Asp.net与Flex交互测试记录

    一.利用asp.net为Flex提供数据服务,flex为前端表现. 二.flex通过三种方式四种代码实现来取数据.分别为     HttpService. WebService. RemoteObje ...

  8. xml string 相互转换

    一.使用最原始的javax.xml.parsers,标准的jdk api // 字符串转XMLString xmlStr = /"....../";StringReader sr ...

  9. win7修改hosts文件方法

    因权限的关系,导致无法修改,解决如下: hosts属性 --> 安全 --> 编辑权限 --> 完全控制,就可以修改该文件了.win7默认不能修改hosts文件.

  10. -高级Javascript编程学习笔记----Javascript编程及架构设计最应该注意的基本点

    最小全局变量 JavaScript通过函数管理作用域.在函数内部生命的变量只在这个函数内部,别的地方不可用.全局变量是指在函数外或是未声明直接简单使用的.每个Javascipt环境有一个全局对象,当你 ...