HDU 4643 GSM

来源:互联网 发布:phpstorm格式化js代码 编辑:程序博客网 时间:2024/05/29 13:17
题意: 求一条线段上的点到其他m个点有多少个最短距离, m个点中没有两点到线段上的端点距离相等~
分析:用一个点和其他点的中垂线所在的半平面划分该点所在的区域, 该区域内任意一个点的距离到该点相对其他点距离最近.
具体实现:用一个足够大的矩形覆盖所有点, 然后划分区域, 最后判断所问线段和多少个区域(凸包)有交点~

#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <string>#include <cstring>#include <vector>#define FOR(i, n) for(int i = 0; i < n; i++)#define MEM(array) memset(array, 0, sizeof(array))#define eps 1e-7#define INF (int)1e5#define PI acos(-1.0)#define MAX 111using namespace std;inline int sgn(const double &x){return x > eps ? 1 : (x < -eps ? -1 : 0);}inline double sqr(const double &x){return x * x;}struct Point {    double x, y;    Point() {}    Point(const double &xx, const double &yy):x(xx), y(yy) {}    friend Point operator + (const Point &b, const Point &a) {        return Point(b.x + a.x, b.y + a.y);    }    friend Point operator - (const Point &b, const Point &a) {        return Point(b.x - a.x, b.y - a.y);    }    Point operator * (const double &a)const{        return Point(x * a, y * a);    }    Point operator / (const double &a) const{        return Point(x / a, y / a);    }    friend double dot(const Point &a, const Point &b) {        return a.x *b.x + a.y * b.y;    }    friend double det(const Point &a, const Point &b) {        return a.x * b.y - a.y * b.x;    }    double len( )const {        return sqrt(dot(*this, *this));    }    bool operator < (const Point &a)const {        return sgn(x - a.x) < 0 || (sgn(x - a.x) == 0 && sgn(y - a.y) > 0);    }    bool operator == (const Point &a)const {        return sgn(x - a.x ) == 0 && sgn(y - a.y) == 0;    }    Point rotate(const double &angle)const{        double x1 = x * cos(angle) - y * sin(angle);        double y1 = x * sin(angle) + y * cos(angle);        return Point(x1, y1);    }    void in() {        scanf("%lf %lf", &x, &y);    }    void out()const {        printf("%.4f    %.4f\n", x, y);    }}c[MAX], b[MAX];int n, m;struct Line{    Point s, t;    Line(){}    Line(const Point &ss, const Point &tt):s(ss), t(tt){}    //获取s t的中垂线的s所在的半平面线(左边)    friend void getPlaneLine(const Line &line, Line &res){        Point mid  = (line.s + line.t)/ 2;        Point fa = line.dir().rotate(PI / 2);        res = Line(mid, mid + fa);    }    //线段和直线    friend bool lineInsectLinevEx(const Line &l1, const Line &lv, Point &res){            int res1 = sgn( det(l1.s - lv.s, lv.t - lv.s) );            int res2 = sgn( det(l1.t - lv.s, lv.t - lv.s) );            if(res1 * res2 < 0){                double s1 = det(l1.s - lv.s, lv.dir()), s2 = det(l1.t - lv.s, lv.dir());                res =  (l1.t * s1 - l1.s * s2 ) /(s1 - s2);                return 1;            }            return 0;    }    //线段和线段, 不包含端点    friend bool lineInsectLineEx(const Line &l1, const Line &l2){        int res1 = sgn( det(l1.s - l2.s, l2.t - l2.s) * det( l1.t - l2.s, l2.t - l2.s) ) ;        int res2 = sgn( det(l2.s - l1.s, l1.t - l1.s) * det( l2.t - l1.s, l1.t - l1.s) ) ;        return res1 < 0 && res2 < 0;    }    Point dir()const{        return t - s;    }    void out()const{        s.out();        t.out();    }};struct Poly{    vector<Point> p;    friend Poly getCut(const Poly &poly, const Line &line){        int tn = poly.p.size();        Poly resp;        for(int i = 0; i < tn; i++){            Point va = poly.p[i] - line.s, vb = line.dir();            int res = sgn(det(va, vb));            if(res <= 0){//in half                resp.p.push_back(poly.p[i]);            }else {                int j = i  - 1, k  = i + 1;                if(j < 0)j = tn - 1;                if(k > tn - 1)k = 0;                int id[] = {j, k};                FOR(kk, 2){                    va = poly.p[id[kk]] - line.s;                    res = sgn(det(va, vb) );                    Point ins;                    Line l1(poly.p[i], poly.p[id[kk]]);                    if(res < 0 && lineInsectLinevEx( l1, line, ins)){                        resp.p.push_back(ins);                    }                }            }        }        return resp;    }    //和线段的是否有交,不包含端点    bool isInsectLineEx(const Line &l1){        if(isContain(l1.s) == true || isContain(l1.t) == true)return true;        int tn = p.size();        for(int i = 0; i < tn; i++){            Line lv(p[i], p[(i + 1)%tn]);            if(lineInsectLineEx(lv, l1))return true;        }        return false;    }    bool isContain(const Point &t){        int sign = 0;        int tn = p.size();        for(int i = 0; i < tn; i++){            int signt = sgn( det( p[i] - t, p[(i + 1)%tn] - t) );            if(signt){                if(sign){                    if(sign != signt )return 0;                }else {                    sign = signt;                }            }else                return  0;        }        return 1;    }}poly[MAX], rect;void init(){    FOR(i, n){        c[i].in();    }    FOR(j, m){        b[j].in();    }}void getPoly(){    FOR(i, m){        Poly cur = rect;        FOR(j, m){              if(j == i)continue;              Line line(b[i], b[j]), res;              getPlaneLine(line, res);//              res.out();              cur = getCut(cur, res);        }        poly[i] = cur;    }}bool v[MAX];int judge(int a, int b){    int ans = 0;    memset(v, 0, sizeof(v));//    for(int i = a;  i < b; i++)太二不能多说    {        for(int j = 0; j < m; j++){            if(poly[j].isInsectLineEx(Line(c[a], c[b]))){                v[j] = 1;            }        }    }    for(int i  = 0; i < m; i++){        if(v[i])ans ++, v[i] = 0;    }    return ans - 1;}void solve(){    int k ,a, b;    cin>>k;    while(k--){        cin>>a>>b;        cout<<judge(a - 1, b - 1)<<endl;    }}int main(){    rect.p.push_back(Point(-INF, -INF));    rect.p.push_back(Point(INF, -INF));    rect.p.push_back(Point(INF, INF));    rect.p.push_back(Point(-INF, INF));    while(cin>>n>>m){        init();        getPoly();        solve();    }    return 0;}/**/


原创粉丝点击