HDU 4643 GSM(計算幾何求線段的中垂線)
題目連結:傳送門
題意:
給定一個圖上面有n個城市,告訴你他們的座標,然後這個圖上有m個訊號站,當我們從一個城市去另外一個城市的過程中所接收的訊號站可能會發生變化,有Q個詢問,a,b 表示求從城市a到城市b的過程中訊號會發生多少次變化。
分析:
對於給定的一條線路,和我們假定的兩個訊號站,如果這兩個訊號站成的線與這條線路不垂直的話,那麼這兩個點到這條線的距離肯定的是先一個大一個小,然後直到兩個相等,然後顛倒過來,另一個大,這一個小,那麼相等的點就是兩個訊號站的垂直平分線與線路的交點,如果交點線上路(線段)上的話而且這個點到這兩個發射站其中一個的距離小於其他所有發射站到這個點的距離那麼就會變化。我們預處理所有發射站的中垂線然後列舉就可以了。
時間複雜度O(Q*n*m*m/2)
程式碼如下:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const double eps = 1e-8;
const double inf = 1e20;
const double pi = acos(-1.0);
const int maxn = 60;
int sgn(int x)
{
if(x == 0)return 0;
if(x < 0)return -1;
else return 1;
}
struct Point
{
double x,y;
Point(){}
Point(double _x,double _y)
{
x = _x;
y = _y;
}
void input()
{
scanf("%lf%lf",&x,&y);
}
bool operator == (Point b)const
{
return sgn(x-b.x) == 0 && sgn(y-b.y) == 0;
}
bool operator < (Point b)const
{
return sgn(x-b.x)== 0?sgn(y-b.y)<0:x<b.x;
}
Point operator -(const Point &b)const
{
return Point(x-b.x,y-b.y);
}
Point operator +(const Point &b)const
{
return Point(x+b.x,y+b.y);
}
//叉積
double operator ^(const Point &b)const
{
return x*b.y - y*b.x;
}
//點積
double operator *(const Point &b)const
{
return x*b.x + y*b.y;
}
};
struct Line
{
Point s,e;
Line(){}
Line(Point _s,Point _e)
{
s = _s;
e = _e;
}
bool operator ==(Line v)
{
return (s == v.s)&&(e == v.e);
}
void input()
{
s.input();
e.input();
}
//兩線段相交判斷
//2 規範相交
//1 非規範相交
//0 不相交
int segcrossseg(Line v)
{
int d1 = sgn((e-s)^(v.s-s));
int d2 = sgn((e-s)^(v.e-s));
int d3 = sgn((v.e-v.s)^(s-v.s));
int d4 = sgn((v.e-v.s)^(e-v.s));
if( (d1^d2)==-2 && (d3^d4)==-2 )return 2;
return (d1==0 && sgn((v.s-s)*(v.s-e))<=0) ||
(d2==0 && sgn((v.e-s)*(v.e-e))<=0) ||
(d3==0 && sgn((s-v.s)*(s-v.e))<=0) ||
(d4==0 && sgn((e-v.s)*(e-v.e))<=0);
}
//直線和線段相交判斷
//-*this line -v seg
//2 規範相交
//1 非規範相交
//0 不相交
int linecrossseg(Line v)
{
int d1 = sgn((e-s)^(v.s-s));
int d2 = sgn((e-s)^(v.e-s));
if((d1^d2)==-2) return 2;
return (d1==0||d2==0);
}
};
Line line[maxn][maxn];
Point p1[maxn],p2[maxn];
//求線段的中垂線
inline Line getMidLine(const Point &a, const Point &b) {
Point mid = (a + b);
mid.x/=2.0;
mid.y/=2.0;
Point tp = b-a;
return Line(mid, mid+Point(-tp.y, tp.x));
}
inline Point intersect(const Point &a, const Point &b, const Point &l, const Point &r) {
Point ret = a;
double t = ((a.x - l.x) * (l.y - r.y) - (a.y - l.y) * (l.x - r.x))
/ ((a.x - b.x) * (l.y - r.y) - (a.y - b.y) * (l.x - r.x));
ret.x += (b.x - a.x) * t;
ret.y += (b.y - a.y) * t;
return ret;
}
inline bool dotOnSeg(const Point &p, const Point &l, const Point &r) { //判點線上段上
return (p.x-l.x)*(p.x-r.x) < eps
&& (p.y-l.y)*(p.y-r.y) < eps;
}
double dis(Point a,Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int n,m;
bool check(const Point &p, int &a) {
double d = dis(p, p2[a]);
for(int i = 0; i < m; i++){
if(i==a) continue;
if(d > dis(p, p2[i])+eps) return 0;
}
return 1;
}
int main()
{
int q;
while(~scanf("%d%d",&n,&m)){
for(int i=0;i<n;i++)
p1[i].input();
for(int i=0;i<m;i++)
p2[i].input();
for(int i=0;i<m;i++){
for(int j=i+1;j<m;j++){
line[i][j]=getMidLine(p2[i],p2[j]);
}
}
scanf("%d",&q);
while(q--){
int a,b;
scanf("%d%d",&a,&b);
if(a==b){
puts("0");
continue;
}
a--,b--;
Line tmp =Line(p1[a],p1[b]);
int ans = 0;
for(int i=0;i<m;i++){
for(int j=i+1;j<m;j++){
if(line[i][j].linecrossseg(tmp)){//判斷直線與線段是否相交
Point c = intersect(p1[a],p1[b],line[i][j].s,line[i][j].e);//求線段與直線的交點
if(dotOnSeg(c, p1[a], p1[b]))
ans+=check(c,i);
}
}
}
printf("%d\n",ans);
}
}
return 0;
}
相關文章
- 【計算幾何】線段相交
- 【計算幾何】求線段相交交點座標
- POJ 1039-Pipe(計算幾何-線段相交、求交點)
- POJ 2991 Crane(線段樹+計算幾何)
- POJ 1127-Jack Straws(計算幾何 線段相交)
- 【計算幾何】點定位(線段,三角形,多邊形)
- 三維幾何生成:多段線、圓弧
- 線段樹 transformation——hdu 4578ORM
- POJ 1584-A Round Peg in a Ground Hole(計算幾何-凸包、點到線段距離)
- hdu4288 離線處理線段樹
- BZOJ 1043: [HAOI2008]下落的圓盤 計算幾何,貪心,線段交
- hdu 1754 I Hate It (線段樹)
- 計算幾何
- Transformation HDU - 4578線段樹綜合操作ORM
- hdu 1754 【線段樹/RMQ】I Hate ItMQ
- hdu 3973 字串hash+線段樹字串
- hdu 2665 可持久化線段樹求區間第K大值(函式式線段樹||主席樹)持久化函式
- halcon xld線段中點、端點和角度的計算
- 計算幾何:模板
- 計算幾何模板
- HDU 1754 I Hate It 線段樹入門
- HDU 1077Catching Fish(簡單計算幾何)
- HDU-1466 計算直線的交點數 DP
- HDU 3333 Turing Tree(線段樹+離線操作)
- HDU 6055 Regular polygon(幾何)Go
- [筆記] 計算幾何筆記
- HDU 4606 Occupy Cities (計算幾何+最短路+最小路徑覆蓋)
- 計算幾何_向量的實現
- HDU 1466 計算直線的交點數(簡單dp)
- arcgis api for flex求線段的起點,終點和中點APIFlex
- HDU 1754 I Hate It (線段樹 區間最值)
- hdu 1394 Minimum Inversion Number 【線段樹查詢】
- HDU 1556 Color the ball 線段樹入門題
- hdu 4836 The Query on the Tree(線段樹or樹狀陣列)陣列
- HDU 1698 Just a Hook (線段樹區間更新)Hook
- Points on Cycle (hdu1700,幾何)
- 【計算幾何】向量表示
- 【總結】計算幾何模板