POJ-2318 TOYS 计算几何 判断点在线段的位置

题目链接:https://cn.vjudge.net/problem/POJ-2318

题意

在一个矩形内,给出n-1条线段,把矩形分成n快四边形

问某些点在那个四边形内

思路

二分+判断点与位置关系

提交过程

WA*n x1和x2,y1和y2在复制的时候没分清(哭
WA 可能存在二分问题?
AC

代码

#define PI 3.1415926
#include <cmath>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const double eps=1e-10;
const int maxn=5e3+20;

struct Point{
    double x, y;

    Point(int x=0, int y=0):x(x), y(y) {}
    // no known conversion for argument 1 from ‘Point‘ to ‘Point&‘
    Point operator + (Point p){return Point(x+p.x, y+p.y);}
    Point operator - (Point p){return Point(x-p.x, y-p.y);}
    Point operator * (double k){return Point(k*x, k*y);}
    Point operator / (double k){return Point(x/k, y/k);}
    bool operator < (Point p) const{return (x==p.x)?(y<p.y):(x<p.x);}   // need eps?
    bool operator == (const Point p) const{return fabs(x-p.x)<eps&&fabs(y-p.y)<eps;}
    double norm(void){return x*x+y*y;}
    double abs(void){return sqrt(norm());}
    double dot(Point p){return x*p.x+y*p.y;}        // cos
    double cross(Point p){return x*p.y-y*p.x;}      // sin
};
struct Segment{Point p1, p2;};
struct Circle{Point o; double rad;};
typedef Point Vector;
typedef vector<Point> Polygon;
typedef Segment Line;

int ccw(Point p0, Point p1, Point p2){
    Vector v1=p1-p0, v2=p2-p0;
    if (v1.cross(v2)>eps) return 1;         // anti-clockwise
    if (v1.cross(v2)<-eps) return -1;       // clockwise
    if (v1.dot(v2)<0) return 2;
    if (v1.norm()<v2.norm()) return -2;
    return 0;
}

Point project(Segment s, Point p){
    Vector base=s.p2-s.p1;
    double k=(p-s.p1).cross(base)/base.norm();
    return s.p1+base*k;
}

Point reflect(Segment s, Point &p){
    return p+(project(s, p)-p)*2;
}

double lineDist(Line l, Point p){
    return abs((l.p2-l.p1).cross(p-l.p1)/(l.p2-l.p1).abs());
}

double SegDist(Segment s, Point p){
    if ((s.p2-s.p1).dot(p-s.p1)<0) return Point(p-s.p1).abs();
    if ((s.p1-s.p2).dot(p-s.p2)<0) return Point(p-s.p2).abs();
    return abs((s.p2-s.p1).cross(p-s.p1)/(s.p2-s.p1).abs());
}

bool intersect(Point p1, Point p2, Point p3, Point p4){
    return ccw(p1, p2, p3)*ccw(p1, p2, p4)<=0 &&
            ccw(p3, p4, p1)*ccw(p3, p4, p2)<=0;
}

Point getCrossPoint(Segment s1, Segment s2){
    Vector base=s2.p2-s2.p1;
    double d1=abs(base.cross(s1.p1-s2.p1));
    double d2=abs(base.cross(s1.p2-s2.p1));
    double t=d1/(d1+d2);
    return s1.p1+(s1.p2-s1.p1)*t;
}

double area(Polygon poly){
    double res=0; long long size=poly.size();
    for (int i=0; i<poly.size(); i++)
        res+=poly[i].cross(poly[(i+1)%size]);
    return abs(res/2);
}

int contain(Polygon poly, Point p){
    int n=poly.size();
    bool flg=false;
    for (int i=0; i<n; i++){
        Point a=poly[i]-p, b=poly[(i+1)%n]-p;
        if (ccw(poly[i], poly[(i+1)%n], p)==0) return 1;    // 1 means on the polygon.
        if (a.y>b.y) swap(a, b);
        if (a.y<0 && b.y>0 && a.cross(b)>0) flg=!flg;
    }return flg?2:0;                                        // 2 fo inner, 0 for outer.
}

Polygon convexHull(Polygon poly){
    if (poly.size()<3) return poly;
    Polygon upper, lower;
    sort(poly.begin(), poly.end());
    upper.push_back(poly[0]); upper.push_back(poly[1]);
    lower.push_back(poly[poly.size()-1]); lower.push_back(poly[poly.size()-2]);
    for (int i=2; i<poly.size(); i++){
        for (int n=upper.size()-1; n>=1 && ccw(upper[n-1], upper[n], poly[i])!=-1; n--)
            upper.pop_back();
        upper.push_back(poly[i]);
    }
    for (int i=poly.size()-3; i>=0; i--){
        for (int n=lower.size()-1; n>=1 && ccw(lower[n-1], lower[n], poly[i])!=-1; n--)
            lower.pop_back();
        lower.push_back(poly[i]);
    }
    for (int i=1; i<lower.size(); i++)
        upper.push_back(lower[i]);
    return upper;
}

Segment seg[maxn];
int n, m;
int solve(Point p){
    int l=0, r=n;
    while (l<r){
        int mid=l+(r-l)/2;
        if (ccw(seg[mid].p1, seg[mid].p2, p)==-1) r=mid;
        else l=mid+1;
    }
    for (int i=max(l-3, 0); i<=min(l+3, n); i++)
        if (ccw(seg[i].p1, seg[i].p2, p)==-1)
            return l;
}

int main(void){
    long long x, y, x1, y1, x2, y2, xt1, xt2;

    while (scanf("%d", &n)==1 && n){
        int bin[maxn]={0};
        scanf("%d%lld%lld%lld%lld", &m, &x1, &y1, &x2, &y2);
        for (int i=0; i<n; i++){
            scanf("%lld%lld", &xt1, &xt2);
            seg[i].p1=Point(xt1-x1, y1-y2);
            seg[i].p2=Point(xt2-x1, y2-y2);
        }
        seg[n].p1=Point(x2-x1, y1-y2);
        seg[n].p2=Point(x2-x1, y2-y2);

        while (m--){
            scanf("%lld%lld", &x, &y);
            bin[solve(Point(x-x1, y-y2))]++;
        }
        for (int i=0; i<=n; i++)
            printf("%d: %d\n", i, bin[i]);
        printf("\n");
    }

    return 0;
}
Time Memory Length Lang Submitted
204ms 716kB 4134 G++ 2018-08-01 12:19:23

原文地址:https://www.cnblogs.com/tanglizi/p/9403386.html

时间: 2024-10-29 00:55:19

POJ-2318 TOYS 计算几何 判断点在线段的位置的相关文章

poj 2318 TOYS(计算几何 点与线段的关系)

TOYS Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 12015   Accepted: 5792 Description Calculate the number of toys that land in each bin of a partitioned toy box. Mom and dad have a problem - their child John never puts his toys away w

poj 2318 TOYS(判点与线段的关系)

TOYS Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 11643   Accepted: 5616 Description Calculate the number of toys that land in each bin of a partitioned toy box. Mom and dad have a problem - their child John never puts his toys away w

POJ 2318 TOYS(计算几何)

跨产品的利用率推断点线段向左或向右,然后你可以2分钟 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 5005; int n, m, x1, y1, x2, y2; struct Point { int x, y; Point() {} Point(int x, int y) { this->x = x; this-&g

【POJ】2318 TOYS ——计算几何+二分

TOYS Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10281   Accepted: 4924 Description Calculate the number of toys that land in each bin of a partitioned toy box. Mom and dad have a problem - their child John never puts his toys away w

POJ 2318 TOYS(叉积+二分or暴力)

题目链接:POJ 2318 TOYS [写在前面]前几天跟队友分了方向,学渣开始进行计算几何的专题了,真是脑壳有点痛啊.但是我想做多了就没这么坑爹了 [题意]大体意思就是给你一个矩形,有被若干直线分成N个格子,给出M个点的坐标,问你每个点位于哪个格子中. [思路]其实就是点在凸四边形内的判断,然后就可以利用叉积的性质,当然可以用暴力枚举也可以过,但是时间复杂度有点高,最好是用二分求解.(一直觉得二分真是牛逼啊) 下面贴AC代码,用二分219MS就过了: 1 /* 2 ** POJ 2318 TO

poj 2318 TOYS &amp; poj 2398 Toy Storage (叉积)

链接:poj 2318 题意:有一个矩形盒子,盒子里有一些木块线段,并且这些线段坐标是按照顺序给出的, 有n条线段,把盒子分层了n+1个区域,然后有m个玩具,这m个玩具的坐标是已知的,问最后每个区域有多少个玩具 分析:从左往右,直到判断玩具是否在线段的逆时针方向为止,这个就需要用到叉积,当然可以用二分查找优化. 叉积:已知向量a(x1,y1),向量b(x2,y2),axb=x1*y2-x2*y1, 若axb>0,a在b的逆时针方向,若axb<0,则a在b的顺时针方向 注:每组数据后要多空一行

POJ 2318 TOYS 叉积的应用

A - TOYS Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 2318 Appoint description:  lijunle  (2011-07-18)System Crawler  (2016-05-08) Description Calculate the number of toys that land in each b

POJ 3304 Segments(判断直线与线段是否相交)

http://poj.org/problem?id=3304 等价于是否存在一条直线穿过所有线段 判断直线与线段是否相交: 首先用两点p1,p2确定了一条直线 在用p1,p2分别与计算线段两个端点计算叉乘即可 ,叉乘之积>0就说明线段两端点在直线的同侧,也就是直线不经过此线段 注意顺序不要搞反了 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #incl

poj 2318 TOYS (点与线段位置关系判断)

TOYS Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10848   Accepted: 5206 Description Calculate the number of toys that land in each bin of a partitioned toy box. Mom and dad have a problem - their child John never puts his toys away w