UVALive 5908 Tracking RFIDs(计算几何+数据结构,暴力也可过)

A - Tracking RFIDs
Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu
Appoint description: 

Description

Download as PDF

Jeroen operates a warehouse storage facility for the North Western Electrical Resource Company (NWERC). When a customer places an order with NWERC, this order is conveyed to the warehouse. Jeroen's task is to then find the products ordered, pack them into a box, and ship them to the customer.

NWERC has an unusual warehouse policy: the products are not arranged in any particular order, and are strewn all over the place. However, it is possible for Jeroen to do his job because each product is tracked using RFID technology (Objects, that have a radio-frequency identification (RFID) tag attached, can be tracked using radio waves). Specifically, each product is assigned a wireless RFID chip as soon as it enters the warehouse, and sensors located on the warehouse ceiling are used to automatically track the products.

By default, each sensor has a range of r units -- that is, it can read any RFID chip that is located at most r units from it in a straight line. However, if the line segment between a sensor and a product intersects with or touches x walls, the range of the sensor is reduced by xunits in that direction. Furthermore, the sensors may fail to read an RFID chip due to interference from other sensors, so the distance between any pair of sensors in the warehouse is guaranteed to be at least r units. You may further assume that no sensor or product is placed on a wall.

Jeroen now wants to determine, for each product, which sensors can read its RFID chip. Can you help him?

\epsfbox{p5908.eps}

Illustration of sensors, walls and products as in the Sample Input.

Input

On the first line one positive integer: the number of test cases, at most 100. After that per test case:


  • one line with four integers s(1$ \le$s$ \le$250000)r(1$ \le$r$ \le$20)w(0$ \le$w$ \le$10) and p(1$ \le$p$ \le$10000) where s represents the number of sensors, r the range of each sensor, w the number of walls and p the number of products.
  • s lines containing two integers xi and yi(- 10000$ \le$xiyi$ \le$10000). Each such line represents a sensor at location (xiyi). The distance between any pair of sensors is guaranteed to be at least r units.
  • w lines containing four integers bxibyi , exi and eyi(- 10000$ \le$bxibyiexieyi$ \le$10000). Each such line represents a wall, which should be considered as straight line segment from (bxibyi) to (exieyi). The length of this line segment will be positive.
  • p lines, each containing two integers pxi and pyi(- 10000$ \le$pxipyi$ \le$10000). Each such line represents a product at location (pxi,pyi).

Output

Per test case:


  • p lines, each representing a product in the order they appear in the input. Each line should contain an integer t, the number of sensors that can track the product; this integer should then be followed by a list of t ordered pairs representing the corresponding sensor locations. If there are multiple sensors, they should be sorted in increasing order by x-coordinate. If multiple sensors have the same x-coordinate, they should be sorted in increasing order by y-coordinate.

Sample Input

1
4 3 4 7
0 0
-1 3
2 3
11 5
-4 -1 5 -1
3 4 6 1
11 4 11 3
12 5 12 8
1 1
0 -2
4 4
11 2
13 5
13 7
14 5

Sample Output

3 (-1,3) (0,0) (2,3)
1 (0,0)
0
0
1 (11,5)
0
0


直接暴力搞可以过,具体题解参考:http://blog.csdn.net/u012997373/article/details/39521035

感谢这位博主让我查到了错误,其他都写对了,就判断两线段是否相交那里出错了,查了整整2天....

我有两份代码,一份是暴力的,一份是用数据结构优化的。既然大家都是用暴力过的,那我就贴数据结构优化的。(秉着每道水题都当做大数据题来做的心态...

暴力过,时间1.5s-1.8s,数据结构优化:450ms左右,显然,快了一个级别。

代码如下:

//Hello. I'm Peter.
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double ld;
#define peter cout<<"i am peter"<<endl
#define input freopen("data.txt","r",stdin)
#define randin srand((unsigned int)time(NULL))
#define INT (0x3f3f3f3f)*2
#define LL (0x3f3f3f3f3f3f3f3f)*2
#define gsize(a) (int)a.size()
#define len(a) (int)strlen(a)
#define slen(s) (int)s.length()
#define pb(a) push_back(a)
#define clr(a) memset(a,0,sizeof(a))
#define clr_minus1(a) memset(a,-1,sizeof(a))
#define clr_INT(a) memset(a,INT,sizeof(a))
#define clr_true(a) memset(a,true,sizeof(a))
#define clr_false(a) memset(a,false,sizeof(a))
#define clr_queue(q) while(!q.empty()) q.pop()
#define clr_stack(s) while(!s.empty()) s.pop()
#define rep(i, a, b) for (int i = a; i < b; i++)
#define dep(i, a, b) for (int i = a; i > b; i--)
#define repin(i, a, b) for (int i = a; i <= b; i++)
#define depin(i, a, b) for (int i = a; i >= b; i--)
#define pi acos(-1.0)
#define eps 1e-6
#define MOD 1000000007
#define MAXN 50100
#define N 300100
#define M 10100
struct Point
{
    double x,y;
    Point(){};
    Point(double xx,double yy):x(xx),y(yy){};
}sensor[N],wall1[100],wall2[100];
typedef Point Vector;
void readPoint(Point &a){//输入一个点
    scanf("%lf %lf",&a.x,&a.y);
}
double sq(double x){//x^2
    return x*x;
}
int dcmp(double x){//判断x正负或为0
    if(fabs(x)<eps) return 0;
    else if(x<0) return -1;
    else return 1;
}
Vector operator +(const Vector a,const Vector b){//两向量相加
    return Vector(a.x+b.x,a.y+b.y);
}
Vector operator -(const Vector a,const Vector b){//两向量相减
    return Vector(a.x-b.x,a.y-b.y);
}
bool operator ==(const Vector a,const Vector b){//判断两点或两向量是否一致
    return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0;
}
double operator *(const Vector a,const Vector b){//两向量点乘
    return a.x*b.x+a.y*b.y;
}
double operator &(const Vector a,const Vector b){//两向量叉积
    return a.x*b.y-a.y*b.x;
}
Vector operator *(const Vector b,const double a){//一个数*一个向量
    return Vector(a*b.x,a*b.y);
}
Vector operator *(const double a,const Vector b){//一个向量*一个数
    return Vector(a*b.x,a*b.y);
}
double Length(Vector b){//求一个向量的长度
    return sqrt(b*b);
}
double DistancePointToPoint(Point a,Point b){//求点到点的无向距离
    return Length(a-b);
}
bool SegmentBananaSegment(Point p1,Point p2,Point w1,Point w2){//判断两线段是否香蕉
    if (fmin (p1.x, p2.x) > fmax (w1.x, w2.x) ||
        fmin (p1.y, p2.y) > fmax (w1.y, w2.y) ||
        fmin (w1.x, w2.x) > fmax (p1.x, p2.x) ||
        fmin (w1.y, w2.y) > fmax (p1.y, p2.y))
        return false;
    double x1=(w2-w1)&(p1-w1);
    double x2=(w2-w1)&(p2-w1);
    double x3=(p2-p1)&(w1-p1);
    double x4=(p2-p1)&(w2-p1);
    return dcmp(x1*x2)<=0 && dcmp(x3*x4)<=0;
}
//Circle
struct Circle
{
    Point c;
    double r;
    Circle(){};
    Circle(Point c,double r):c(c),r(r){};
    Point point(double a){
        return Point(c.x+cos(a)*r,c.y+sin(a)*r);
    }
};
void readCircle(Circle &c1,Point p,double r){//输入一个圆
    c1.c=p;
    c1.r=r;
}
int LineBananaCircle(Point p,Vector v,Circle c,vector<Point>&poi){//求一条线和一个圆的交点。三种情况
    double a1=v.x,b1=p.x-c.c.x,c1=v.y,d1=p.y-c.c.y;
    double e1=sq(a1)+sq(c1),f1=2*(a1*b1+c1*d1),g1=sq(b1)+sq(d1)-sq(c.r);
    double delta=sq(f1)-4*e1*g1,t;
    if(dcmp(delta)<0) return 0;
    else if(dcmp(delta)==0){
        t=(-f1)/(2*e1);poi.pb(p+v*t);
        return 1;
    }
    else{
        t=(-f1+sqrt(delta))/(2*e1);poi.pb(p+v*t);
        t=(-f1-sqrt(delta))/(2*e1);poi.pb(p+v*t);
        return 2;
    }
}
int num_sen,num_wall,num_pro;
double r;
vector<int>ycor[MAXN];
struct Data{
    int x,y;
}d;
vector<Data>ans[MAXN];
bool comp(const Data a,const Data b){
    if(a.x!=b.x) return a.x<b.x;
    else return a.y<b.y;
}
void caculate_ans(vector<int>ycor[],int y,int k1,int k2,Point pro,int k){
    repin(i,k1,k2){
        sensor[0].y=y;
        sensor[0].x=ycor[y][i];
        int num_b=0;
        repin(j,1,num_wall){
            if(SegmentBananaSegment(pro,sensor[0],wall1[j],wall2[j])){
                num_b+=1;
            }
        }
        double rt=r-num_b;
        double dis=DistancePointToPoint(sensor[0],pro);
        if(dcmp(rt-dis)>=0){
            d.x=(int)sensor[0].x-M;
            d.y=(int)sensor[0].y-M;
            ans[k].pb(d);
        }
    }
}
int main()
{
    int T;
    cin>>T;
    while(T--){
        scanf("%d %lf %d %d",&num_sen,&r,&num_wall,&num_pro);
        repin(i,0,M<<1){
            ycor[i].clear();
        }
        repin(i,1,num_sen){
            readPoint(sensor[i]);
            sensor[i].x+=M,sensor[i].y+=M;
            int y=(int)sensor[i].y;
            ycor[y].pb((int)sensor[i].x);
        }
        repin(i,0,M<<1){
            int len=gsize(ycor[i]);
            if(len>0){
                sort(ycor[i].begin(),ycor[i].end());
            }
        }
        repin(i,1,num_wall){
            readPoint(wall1[i]);
            wall1[i].x+=M,wall1[i].y+=M;
            readPoint(wall2[i]);
            wall2[i].x+=M,wall2[i].y+=M;
        }
        repin(i,1,num_pro){
            ans[i].clear();
        }
        Point pro;
        repin(i,1,num_pro){
            readPoint(pro);
            pro.x+=M,pro.y+=M;
            repin(j,(int)(pro.y-r),(int)(pro.y+r)){
                int leny=gsize(ycor[j]);
                if(!leny) continue;
                vector<Point>poi;
                poi.clear();
                Circle c;
                readCircle(c,pro,r);
                Point pt(pro.x-r,j);
                Vector vt(1,0);
                int num=LineBananaCircle(pt,vt,c,poi);
                if(num==2){
                    Point p1=poi[0],p2=poi[1];
                    if(dcmp(p1.x-p2.x)>0) swap(p1,p2);
                    int x=(int)p1.x;
                    if(p1.x-x>0) p1.x=x+1;
                    p2.x=(int)p2.x;
                    int k1=(int)(lower_bound(ycor[j].begin(),ycor[j].end(),(int)p1.x)-ycor[j].begin());
                    int k2=(int)(upper_bound(ycor[j].begin(),ycor[j].end(),(int)p2.x)-ycor[j].begin())-1;
                    if(k1>k2) continue;
                    caculate_ans(ycor,j,k1,k2,pro,i);
                }
                else if(num==1){
                    Point p=poi[0];
                    int k1=(int)(lower_bound(ycor[j].begin(),ycor[j].end(),(int)p.x)-ycor[j].begin());
                    int k2=(int)(upper_bound(ycor[j].begin(),ycor[j].end(),(int)p.x)-ycor[j].begin())-1;
                    if(k1>k2) continue;
                    caculate_ans(ycor,j,k1,k2,pro,i);
                }
            }
        }
        repin(i,1,num_pro){
            int len=gsize(ans[i]);
            if(len>0){
                sort(ans[i].begin(),ans[i].end(),comp);
            }
            printf("%d",len);
            rep(j,0,len){
                printf(" (%d,%d)",ans[i][j].x,ans[i][j].y);
            }
            printf("\n");
        }
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值