HDU 4643 GSM 算术几何
当火车处在换基站的临界点时,它到某两基站的距离相等。因此换基站的位置一定在某两个基站的中垂线上,
我们预处理出任意两基站之间的中垂线,对于每次询问,求询问线段与所有中垂线的交点。
检验这些交点是否满足条件(详见代码),如果满足,那么它是一个交换点。
#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 算术几何的更多相关文章
- hdu 4643 GSM 计算几何 - 点线关系
/* hdu 4643 GSM 计算几何 - 点线关系 N个城市,任意两个城市之间都有沿他们之间直线的铁路 M个基站 问从城市A到城市B需要切换几次基站 当从基站a切换到基站b时,切换的地点就是ab的 ...
- HDU 4643 GSM (2013多校5 1001题 计算几何)
GSM Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submiss ...
- hdu 4643 GSM(暴力)
GSM Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Total Submis ...
- HDU 4643 GSM 简单计算几何
今天比赛的时候略坑, admin告诉我询问Q的个数不超过n^2, 赛后敲了个 O(Q*m^3)的复杂度,但这个复杂度常数比较低,可能在除以个小常数, 300ms过了,真心无语,数据应该水了吧,比赛的时 ...
- HDU 4643 GSM 暑期多校联合训练第五场 1001
点击打开链接 我就不说官方题解有多坑了 V图那么高端的玩意儿 被精度坑粗翔了 AC前 AC后 简直不敢相信 只能怪自己没注意题目For the distance d1 and d2, if fabs( ...
- hdu 4643(计算几何)
题意:容易理解 分析:切换的地点为两个基站所在直线的中垂线与两座城市所在直线的交点. 代码实现: #include <cstdio> #include <cmath> #inc ...
- hdu 5605 geometry(几何,数学)
Problem Description There is a point P at coordinate (x,y). A line goes through the point, and inter ...
- MT【23】用算术几何不等式证明数列极限存在
评:如果不需要精确到3,上界的求法可以利用$$(1+\frac{1}{n})^n*\frac{1}{2}*\frac{1}{2}<(\frac{n+\frac{1}{n}*n+\frac{1}{ ...
- hdu 6097 Mindis(数学几何,圆心的反演点)
Mindis Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Subm ...
随机推荐
- JavaScript DOM动态创建(声明)Object元素
http://www.cnblogs.com/GuominQiu/archive/2011/04/01/2002783.html 一文提及“等整个页面加载完毕后,根据用户所选的阅读机类型,再用Java ...
- 文件读写器FileRW 1.0发布
这个软件未发布前,当年被计算机杂志报道过. FileRW 文件读写器 1.0功能介绍:1.可以以各种方式读普通文件和I/O文件.2.可以以各种方式写文件.3.可以配置文件的分享读写方式.4.可以指定文 ...
- Spring与apache CXF结合实例
本文的前提是已经有一个Spring的项目,在此基础上如何跟apache CXF进行结合,开发出WebService服务和调用WebService服务. 1.开发WebService 1.引入jar ...
- ExtJS登陆页面涉及到的几个问题
1.如何在文本框中增加提示信息 输入框中无法直接使用tooltip,需要使用单独的代码 var tip = Ext.create('Ext.tip.ToolTip', { target : ...
- eclipse部署Tomcat6 : The server does not support version 3.0 of the JEE Web module specification
为项目添加tomcat 6,发现不能添加,原因如下 这是因为Tomcat6不能为JavaEE3.0版本服务,把项目的版本降低到2.5就可以了 现在可以部署了
- poj 1463 Strategic game
题目链接:http://poj.org/problem?id=1463 题意:给出一个无向图,每个节点只有一个父亲节点,可以有多个孩子节点,在一个节点上如果有一位战士守着,那么他可以守住和此节点相连的 ...
- 【BZOJ】【1863】【ZJOI2006】trouble 皇帝的烦恼
二分+DP Orz KuribohG 神题啊= = 满足单调性是比较显然的…… 然而蒟蒻并不会判断能否满足……QwQ 神一样的DP姿势:f[i]表示第 i 个与第1个最多有多少个相同,g[i]表示最少 ...
- Notes on the Dirichlet Distribution and Dirichlet Process
Notes on the Dirichlet Distribution and Dirichlet Process In [3]: %matplotlib inline Note: I wrote ...
- pragma伪指令
pragma伪指令 通过pragma伪指令告诉编译器如何对待特定的函数.对象或代码段.TMS320C28x C/C++编译器支持如下形式的pragma伪指令: CODE_SECTION(func,“s ...
- Sqlite基础及其与SQLServer语法差异
1 TOP 这是一个大家经常问到的问题,例如在SQLSERVER中可以使用如下语句来取得记录集中的前十条记录: SELECT TOP 10 * FROM [index] ORDER BY indexi ...