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

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

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

#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. Windows窗体应用程序(非Console)使用libuv实现简单的异步WEB服务器

    libuv是一个很强大的异步处理框架(严格意义上不能叫框架,其实就是一组异步函数库,当然框架这东西有各种各样的定义和理解_^...),最初的的目的是用于NODEJS的异步处理,不过因为它是一个独立的项 ...

  2. WC2016游记

    出发的时候,长沙忽然就出了太阳,明媚而和煦. [day0 25] 噫吁嚱,危乎高哉!蜀道之难,难于上青天! 总之本来上午已经准备好9:50的飞机…然后就在一次次的手机查询中变成了5点多…然后也不是直飞 ...

  3. 【BZOJ】【1640】【USACO2007 Nov】/【1692】【USACO2007 Dec】队列变换

    后缀数组/贪心 每次从等待序列的头或尾拿出一个放到答案序列的末尾,那么每次贪心比较头和尾的字典序大小即可…… TAT贪心很好想,但是我一开始没想到是可以直接比较字符串大小……而是一位一位判的,WA了… ...

  4. WinHex分析PE格式(1)

    最近在一直努力学习破解,但是发现我的基础太差了,就想学习一下PE结构.可是PE结构里的结构关系太复杂,看这老罗的WiN32汇编最后一章 翻两页又合上了..把自己的信心都搞没了.感觉自己的理解能力不行, ...

  5. ios 5

    1.屏幕尺寸568×2/320×2  需要一张568h@2x.png的图片. 2.iOS5不支持udid,用uuid替代,取得uuid方法: -(NSString*) uuid { CFUUIDRef ...

  6. Node.js NPM国内镜像

    NPM国内镜像 http://npm.hacknodejs.com/ http://registry.npmjs.vitecho.com/ https://registry.npm.taobao.or ...

  7. Ckeditor 中一些核心的对象的作用

    1.CKEditor CKEditor对象用于掌管全局,他是一个单例对象,管理着所有实例化了的编辑框. 通过replace方法创建编辑框实例. 2.CKEditor.editor 表示一个编辑框实例, ...

  8. PC端模拟手机浏览网页

    很多网站都通过User-Agent来判断浏览器类型,如果是3G手机,显示手机页面内容,如果是普通浏览器,显示普通网页内容. 谷歌Chrome浏览器,可以很方便地用来当3G手机模拟器.在Windows的 ...

  9. POJ 3181 Dollar Dayz (完全背包,大数据运算)

    题意:给出两个数,n,m,问1~m中的数组成n,有多少种方法? 这题其实就相当于 UVA 674 Coin Change,求解一样 只不过数据很大,需要用到高精度运算... 后来还看了网上别人的解法, ...

  10. Bit-Map

    昨日读July大神<教你如何迅速秒杀掉:99%的海量数据处理面试题>博客,有这么一题与大家分享: 给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断 ...