您的位置:首页 > 其它

POJ 2318 TOYS <计算几何>

2017-11-05 17:10 302 查看
题目

分析:就是给一些点的坐标,判断它属于哪个区域。容易想到用以此点和右边界外一点为端点的线段与partition求相交情况,因为划分线段partition是有序的,所以我们可以用二分,求右方向最近相交的是哪一条线段,就可以知道属于哪个区域了。

代码

#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define V Point
using namespace std;

const double eps=1e-8;
const int MAXN=5e3+5;

struct Point{
double x,y;
Point(){}
Point(double _x,double _y):x(_x),y(_y){}
V operator-(Point p){
return Point(x-p.x,y-p.y);
}
};

int dblcmp(double x){
return fabs(x)<eps?0:(x>0?1:-1);
}

double det(V v1,V v2){
return v1.x*v2.y-v1.y*v2.x;
}

bool cross(Point a,Point b,Point c,Point d){
return (dblcmp(det(b-a,c-a))^dblcmp(det(b-a,d-a)))==-2&&
(dblcmp(det(d-c,a-c))^dblcmp(det(d-c,b-c)))==-2;
}

struct Segment{
Point p1,p2;
Segment(){}
Segment(Point pp1,Point pp2):p1(pp1),p2(pp2){}
bool intersection(Segment s){
return cross(p1,p2,s.p1,s.p2);
}
};

int n,m,cas;
Segment partion[MAXN];
Point endp;
int counte[MAXN];

void counter(Point p){
int l=0,r=n,mid;
while(l<r){
mid=l+(r-l)/2;
if(partion[mid].intersection(Segment(p,endp))) r=mid;
else l=mid+1;
}
++counte[l];
}

void output(){
if(cas++) putchar('\n');
for(int i=0;i<=n;++i){
printf("%d: %d\n",i,counte[i]);
}
}

int main(){
cas=0;
while(scanf("%d",&n),n){
memset(counte,0,sizeof counte);
double x,y,x1,y1,x2,y2,U,L;
scanf("%d %lf %lf %lf %lf",&m,&x1,&y1,&x2,&y2);
for(int i=0;i<n;++i){
scanf("%lf %lf",&U,&L);
partion[i]=Segment(Point(U,y1),Point(L,y2));
}
partion
=Segment(Point(x2,y2),Point(x2,y1));
endp=Point(x2+1,(y1+y2)/2.0);
for(int i=0;i<m;++i){
scanf("%lf %lf",&x,&y);
counter(Point(x,y));
}
output();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj