ps:如果这是第一次接触半平面交,不要认为它是很个高深的东东.其实以你现在的几何水平完全能够YY写出它.
半平面: 对一条直线,它将整个平面分成了两部分,对于其中的每一部分.就叫做一个半平面.(这个应该好理解吧)
现在我们要保留其中一个半平面, 可以用向量的左边,右边来标记, 还可以用 Ax+By+C 与 0的关系来标记(这里你千万别纠结它是在直线上方呢,还是下方,而让自己糊涂了),对于上面的两种剖分平面的方式, 你当然还可以用其他的条件,比如: Ax+By+C 与 10 的关系, 我举这个例子只是想说明:
你只要给出一个条件就行, 对于该条件必有成立与不成立两部分,这样就把整个平面分成了两部分了.
当然我们一般用的上面的两种..
废话说了一大托..
赶紧把这个秒了:
题目: 给一个凸多边形,然后给你一个向量,求该向量左边部分与凸多边形的交集所形成的多边形,然后得出该多边形的点集.
很水吧?不会?再好好想想.......
用这条向量与多边形的每个点判断是否在该向量的左边,每条边是否与该向量所在的直线产生了交点..
有想法了么? 相信只是一些细节没太清楚了?
其实下面的稍微浏览下就行了,,,半平面交N^2算法,你会发现真得很水.
半平面交N^2算法:
对凸多边形,选定一个方向,,对第i个点判断是否满足该 向量的条件,如果满足,把该点加入点集, 然后看i 到i+1这条线段与那条直线是否有交点.有的话加入就行.
ok! 就完了,,,说的一个大概,,你想想自己会怎么写,然后看下下面的写法,综合一下,你就搞定了
#include<iostream> #include<cstdlib> #include<cstdio> #include<cstring> #include<cmath> #define zero(x)((((x)>0?(x):(-(x)))<eps)) using namespace std; double eps=1e-8; double pi=acos(-1); struct P { double x,y; void read(){scanf("%lf%lf",&x,&y);} P(){} P(double x,double y):x(x),y(y){} P operator +(const P& p){return P(x+p.x,y+p.y);} P operator -(const P& p){return P(x-p.x,y-p.y);} P operator /(double d) {return P(x/d,y/d);} P operator *(double d) {return P(x*d,y*d);} P rot(double th){return P(x*cos(th)-y*sin(th),x*sin(th)+y*cos(th));} double operator *(const P p){return x*p.y-y*p.x;} bool operator !=(const P& p){return (zero(x-p.x)&&zero(y-p.y))==false;} }; struct Line { P a,b; Line(){} Line(P a,P b):a(a),b(b){} }; P tp[305],pp[305]; //pp :记录最终的点集 , tp:临时存储用的 int N;//记录点集的数目 P ins_seg(P a1,P b1,P a2,P b2)//直线求交 { double u=(b1-a1)*(a2-a1); double v=(a1-b1)*(b2-b1); return (a2 * v + b2 * u ) / ( u + v ); } void cut(P a,P b)// 用一条有向向量对多变形进行切割,这里是保留向量的右边 { int dn=0; double t1,t2; for(int i=0;i<N;i++)// 枚举每个点 { t1=(b-a)*(pp[i]-a);// 叉积第i个点 t2=(b-a)*(pp[(i+1)%N]-a);//叉积第i+1个点 if(t1<eps)tp[dn++]=pp[i];// 第i个点在向量右边,加入点集中 if(t1*t2<-eps)tp[dn++]=ins_seg(a,b,pp[i],pp[(i+1)%N]);// i到i+1的线段与该向量相交(乘积为负,表明两点不在同一边,必然相交) } N=0; for(int i=0;i<dn;i++)// 把临时存储的点集传给pp里面 if(N==0||pp[N-1]!=tp[i])// 去掉重点.. pp[N++]=tp[i]; }三道水题: 赶紧写了,测模板
POJ 3335 Rotating Scoreboard
http://acm.pku.edu.cn/JudgeOnline/problem?id=3335
POJ 1474 Video Surveillance
http://acm.pku.edu.cn/JudgeOnline/problem?id=1474
POJ 1279 Art Gallery
http://acm.pku.edu.cn/JudgeOnline/problem?id=1279
POJ 3525 Most Distant Point from the Sea (推荐)
http://acm.pku.edu.cn/JudgeOnline/problem?id=3525
备注:题解是白色字体(方便你先思考这个问题)
我当时写这题反正二了,没有想到二分,当时用的枚举第i条,然后切割出在所有边中,到改边是最近的点集集合,这里用角平分线就行切割的,反正我当时写了很久..自己YY如何求角平分线..
正解二分:关键是想到问题等同在该多边形内放一个最大的圆,求半径是多少,余下的你懂的..
备注:题解白色字体
这题,我只想问,你最后过的时候eps取的是多少..反正我跪了..用的 1e-16过的...我同学是 1e-8过的..