NUDT校赛 H Military topography 计算几何 点在多边形内部

题目:https://ac.nowcoder.com/acm/contest/878/H

题意:给出一堆等高线, 问一个点的高度是多少.

思路:就是判断一个点在几个多边形内部.

 

代码:

#include<bits/stdc++.h>
#define fuck(x) std::cout<<"["<<#x<<"->"<<x<<"]"<<endl;
using namespace std;
typedef long long ll;
 
 
//memset(a,0x3f,sizeof(a));
 
 
 
const double EPS = 1e-12;
const int Max_N = 110;
double add(double a, double b) {
    return (fabs(a + b) < EPS * ( fabs(a) + fabs(b) )) ? 0 : (a+ b) ;
}
struct Point {
    double x, y;
    Point() {}
    Point(double x, double y):x(x), y(y) {}
    double dist(Point p) {
        return sqrt( add( (x - p.x)*(x - p.x), (y - p.y)*(y - p.y) ) ) ;
    }
    Point operator - (Point p) {
        return Point( add(x,- p.x), add(y, - p.y)) ;
    }
    bool operator ==(Point p) {
        return (add(x,-p.x) == 0)  && (add(y, -p.y) == 0) ;
    }
    double operator ^(Point p) {
        return add(x * p. y, - y * p.x) ;
    }
} po[Max_N];
//判断点p0是否在线段p1p2内
int on_segment(Point p1, Point p2, Point p0) {
    if (((p1-p0).x * (p2-p0).x <=0 )&& ((p1-p0).y * (p2-p0).y <=0))   // 中间是 &&
        return 1;
    return 0;
}
// 判断线段p1p2与q1是否相交
int intersection(Point p1,Point p2, Point q1,Point q2) {
    double d1=(p2-p1)^(q1-p1);
    double d2=(p2-p1)^(q2-p1);
    double d3=(q2-q1)^(p1-q1);  //--由于前面的特判,低处的交点不作为计算------
    double d4=(q2-q1)^(p2-q1);
    if((d1==0 && on_segment(p1,p2,q1) )
            || (d2==0 && on_segment(p1,p2,q2) )
            // ||(d3==0&& on_segment(q1,q2,p1))     //由于前面的特判,低处的交点不作为计算-
            || (d4==0 && on_segment(q1,q2,p2)))
        return 1;
    else if(d1*d2<0 && d3*d4 <0)    // 中间是 &&
        return 1;
    return 0;
}
// 判断点p是否在线段p1p2上
bool in_segment(Point p1, Point p2, Point p) {
    return ( ((p - p1)^(p2 - p1)) == 0 && on_segment(p1, p2, p)) ;
}
int n, i ;
// 判断点p在任意多边形po[Max_n]内, 顶点按顺时针或逆时针给出
// 在边上返回2, 严格在内返回1, 严格在外返回0
int point_is_inside(Point p) {
    int i, num = 0;
    Point q ;
    q.x = 9999999.0, q.y = p. y ;  //q为平行于x轴 p点射线的终点
    for(i = 0 ; i< n;  i++) {
        if(in_segment(po[i],po[(i+1 ) % n], p ) )
            return 2;
        Point p1, p2 ;
        p1 = po[i], p2 = po[(i+1 ) % n] ;
        if(p1.y == p2.y)  // 特判,射线与重边的处理,交点数为0,不计算
            continue ;
        if(p1.y > p2.y)
            swap(p1, p2) ; // p1为较小点, 特判,低处的交点不计算
        if(intersection( p1, p2, p, q ))
            num ++ ;
    }
    return num & 1 ;
}
 
bool on_edge(Point p) {
    for(i = 0 ; i< n;  i++) {
        if(in_segment(po[i],po[(i+1 ) % n], p ) )
            return 1;
    }
    return 0;
}
 
 
//int main() {
//    int  m, i, j, k = 1, t = 0 ;
//    Point a;
//    while(scanf("%d", & n) && n) {
//        if(t)
//            puts("") ;
//        t++ ;
//        scanf("%d", &m) ;
//        printf("Problem %d:\n", k++) ;
//        for(i = 0 ; i < n; i++)
//            scanf("%lf%lf", &po[i].x, &po[i].y ) ;
//        for(i = 0 ; i< m ; i++) {
//            scanf("%lf%lf", &a.x, &a.y) ;
//            if(point_is_inside(a)) {
//                if(on_edge(a)) {
//                    puts("Onedge");
//                } else
//                    puts("Within") ;
//            } else
//                puts("Outside") ;
//        }
//    }
//    return 0;
//}
//
int main() {
    int num;
    int d;
    int h1;
    scanf("%d%d%d",&num,&d,&h1);
    int allx[100][305];
    int ally[100][305];
    int nn[100];
    for(int i=0; i<=num; i++) {
        scanf("%d",&nn[i]);
        for(int j=0; j<nn[i]; j++) {
            scanf("%d%d",&allx[i][j],&ally[i][j]);
        }
    }
    int w;
    scanf("%d",&w);
    Point a;
    for(int i=0; i<w; i++) {
        scanf("%lf%lf",&a.x,&a.y);
        int cnt=0;
        int onEdge=0;
        for(int j=0; j<=num; j++) {
            for(int k=0; k<nn[j]; k++) {
                po[k].x=allx[j][k];
                po[k].y=ally[j][k];
            }
            n=nn[j];
            if(point_is_inside(a)) {
 
                if(on_edge(a)) {
                    onEdge=1;
                    continue;
                }cnt++;
            }
        }
//        fuck(cnt);
//        fuck(onEdge);
        int ans=h1+(2*cnt-1)*(d/2)+(onEdge==1?d/2:0);
        printf("%d\n",ans);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值