set+几何 LA 5908 Tracking RFIDs

 

题目传送门

题意:给一些传感器,范围在r内,再给一些询问点,问这些点能有几个传感器收到,当有墙隔绝时信号减弱,范围变小

分析:set存储传感器,用set的find来查找是否是传感器。因为询问点少,可以枚举询问点的r的范围的所有整数点,+线段相交新模板:)

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
struct Point    {
    int x, y;
    Point() {}
    Point(int x, int y) : x (x), y (y)  {}
    Point operator - (const Point &r) const {
        return Point (x - r.x, y - r.y);
    }
    bool operator < (const Point &r) const  {
        return x < r.x || (x == r.x && y < r.y);
    }
    int operator ^ (const Point &r) const {     //叉积
        return x * r.y - y * r.x;
    }
    bool operator == (const Point &r) const {
        return (x == r.x && y == r.y);
    }
};
typedef Point Vector;
Point read_point(void)  {
    int x, y;   scanf ("%d%d", &x, &y);
    return Point (x, y);
}
int dot(Vector A, Vector B) {
    return A.x * B.x + A.y * B.y;
}
int cross(Vector A, Vector B)   {
    return A.x * B.y - A.y * B.x;
}
bool on_seg(Point p, Point a, Point b)  {
    return (cross (a - p, b - p) == 0 && dot (a - p, b - p) < 0);
}
//2 规范相交 1 非规范相交 0 不相交  //有误
int can_seg_seg_inter(Point a1, Point a2, Point b1, Point b2)  {
    int c1 = cross (a2 - a1, b1 - a1), c2 = cross (a2 - a1, b2 - a1),
        c3 = cross (b2 - b1, a1 - b1), c4 = cross (b2 - b1, a2 - b1);
    if ((c1 ^ c2) == -2 && (c3 ^ c4) == -2) return 2;
    return (on_seg (a1, b1, b2) || on_seg (a2, b1, b2)
            || on_seg (b1, a1, a2) || on_seg (b2, a1, a2));
}
bool check(Point a1, Point a2, Point b1, Point b2) {
    if (min (a1.x, a2.x) > max (b1.x, b2.x) ||
        min (a1.y, a2.y) > max (b1.y, b2.y) ||
        min (b1.x, b2.x) > max (a1.x, a2.x) ||
        min (b1.y, b2.y) > max (a1.y, a2.y)) return false;
    int c1 = (a1 - a2) ^ (a1 - b1);
    int c2 = (a1 - a2) ^ (a1 - b2);
    int c3 = (b1 - b2) ^ (b1 - a1);
    int c4 = (b1 - b2) ^ (b1 - a2);
    return 1ll * c1 * c2 <= 0 && 1ll * c3 * c4 <= 0;
}
int s, r, w, p;
Point p1[15], p2[15];
set<Point> S;

int squ(int x)   {
    return x * x;
}

int get_dis2(Point a, Point b) {
    return squ (a.x - b.x) + squ (a.y - b.y);
}

bool find_senor(Point a, Point b)    {
    if (S.find (b) != S.end ()) {
        int d2 = get_dis2 (a, b);
        if (d2 > squ (r))   return false;
        int cnt = 0;
        for (int i=1; i<=w; ++i)    {
            //if (can_seg_seg_inter (a, b, p1[i], p2[i]))  cnt++;
            if (check (a, b, p1[i], p2[i]))  cnt++;
        }
        if (cnt > r)    return false;
        return d2 <= squ (r - cnt);
    }
    else    return false;
}

void run(Point a, vector<Point> &vec)   {
    for (int i=-r; i<=r; ++i)    {
        int d = sqrt (squ (r) - squ (i));
        for (int j=-r; j<=r; ++j)    {
            Point b = Point (a.x + i, a.y + j);
            if (find_senor (a, b))  vec.push_back (b);
        }
    }
}

int main(void)  {
    int T;  scanf ("%d", &T);
    while (T--) {
        scanf ("%d%d%d%d", &s, &r, &w, &p);
        S.clear ();
        for (int i=1; i<=s; ++i)    {
            S.insert (read_point ());
        }
        for (int i=1; i<=w; ++i)    {
            p1[i] = read_point ();
            p2[i] = read_point ();
        }
        vector<Point> vec;
        for (int i=1; i<=p; ++i)    {
            Point a = read_point ();
            vec.clear ();
            run (a, vec);
            sort (vec.begin (), vec.end ());
            printf ("%d", vec.size ());
            for (int i=0; i<vec.size (); ++i)   {
                printf (" (%d,%d)", vec[i].x, vec[i].y);
            }
            puts ("");
        }
    }

    return 0;
}

  

posted @ 2016-01-14 21:25  Running_Time  阅读(296)  评论(0编辑  收藏  举报