您的位置:首页 > 其它

poj 2540 Hotter Colder 半平面交

2016-08-23 21:27 429 查看

题目链接

题意:

在一个(0,0) ,(10,0),(10,10),(0,10)四个点围成的正方形房屋内藏着一个人B,现在A蒙着眼从(0,0)出发,之后经过一些点停下,B会告诉他这个位置和上一次比是距自己近了,还是远了。

每一步输出B可能所在区域的面积。

解法:

首先一点,如果是”Same”,那么之后都输出0.00 。

每一步半平面交之后求凸多边形面积。

对于两个连续的停留点A、B,首先确定中点midP,然后v⃗ =AB−→−,之后根据(x,y)∗(y,−x)=0,将v⃗ =(v.y,−v.x),这就求出了中垂线方向上的向量。

我们假定是Colder,那么A点必然在v⃗ 左边,所以直接判断A点v⃗ 是否在左边,如果不是调换v⃗ 的方向,那么现在A点必然在v⃗ 左边,如果这时发现是Hotter,那么再次调换v⃗ 的方向。

这样midP和v⃗ 就构成了一条射线(一个半平面)。

代码:

#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;

#define all(x) (x).begin(), (x).end()
#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)
#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)
#define mes(a,x,s)  memset(a,x,(s)*sizeof a[0])
#define mem(a,x)  memset(a,x,sizeof a)
#define ysk(x)  (1<<(x))
typedef long long ll;
typedef pair<int, int> pii;
const int INF =0x3f3f3f3f;
const int maxn= 100   ;
const double PI=acos(-1.0);
const double eps=1e-10;
int dcmp(double x)
{
if(fabs(x)<eps)  return 0;
else return x<0?-1:1;
}
struct Point
{
double x,y;
Point(double x=0,double y=0):x(x),y(y) {};
bool operator ==(const Point B)const {return dcmp(x-B.x)==0&&dcmp(y-B.y)==0;}

bool operator<(const Point& b)const
{
return dcmp(x-b.x)<0|| dcmp(x-b.x)==0 &&dcmp(y-b.y)<0;
}
};
typedef Point Vector;
Vector operator -(Vector A,Vector B) {return Vector(A.x-B.x,A.y-B.y); }

double Cross(Vector A,Vector B)//叉乘
{
return A.x*B.y-A.y*B.x;
}

double Dot(Vector A,Vector B)//点乘
{
return A.x*B.x+A.y*B.y;
}

Vector operator +(Vector A,Vector B) {return Vector(A.x+B.x,A.y+B.y); }
Vector operator *(Vector A,double p) {return Vector(A.x*p,A.y*p); }
Vector operator /(Vector A,double p) {return Vector(A.x/p,A.y/p); }
Vector operator -(Vector A)  {return  Vector(-A.x,-A.y);}

struct Line
{
Point p,p2;
Vector v;
double ang;
Line(){}
Line(Point a,Vector v):p(a),v(v){ang=atan2(v.y,v.x); }//点线式
void twoPointIntial(Point p,Point p2)//两点式
{
this->p=p;
this->p2=p2;
v=  p2-p;
ang=atan2(v.y,v.x);
}
Point point(double t)//参数方程求参数t对应点
{
return p+v*t;
}
bool operator<(const Line & L)const
{
return ang<L.ang;
}
};

Point GetIntersection(Line a,Line b)
{
Vector u=a.p-b.p;
double t=Cross(b.v,u)/Cross(a.v,b.v);
return a.p+a.v*t;
}

bool OnRight(Line L,Point p)
{
return dcmp(Cross(L.v,p-L.p))<0;
}

int HalfplaneIntersection(Line* L,int n,Point * poly)
{
sort(L,L+n);
int first,last;
Point *p=new Point
;
Line *q=new Line
;
q[first=last=0]=L[0];
for(int i=1;i<n;i++)
{
while(first<last&&OnRight(L[i],p[last-1] ) )  last--;
while(first<last&&OnRight(L[i],p[first]))  first++;
q[++last]=L[i];
if(fabs(Cross(q[last].v,q[last-1].v) )<eps )
{
last--;
if(!OnRight(q[last],L[i].p) )  q[last]=L[i];
}
if(first<last) p[last-1]=GetIntersection(q[last-1],q[last] );
}
while(first<last&&OnRight(q[first],p[last-1])) last--;
if(last-first<=1)  return 0;//小于3个,不存在
p[last]=GetIntersection(q[last],q[first]);

int m=0;
for(int i=first;i<=last;i++) poly[m++]=p[i];
return m;

}

double PolygonArea(Point *p,int n)
{
double area=0;
for(int i=1;i<n-1;i++)
{
area+=Cross(p[i]-p[0],p[i+1]-p[0]);
}
return area/2;
}

Point getMidPoint(Point a,Point b)
{
return Point( (a.x+b.x)/2,(a.y+b.y)/2 );
}
int n,np;
Line L[maxn+10];
Point p[maxn+10],poly[maxn+10];
string s;

int main()
{
std::ios::sync_with_stdio(false);
double x,y;
bool zero=0;n=0;
L[n++].twoPointIntial(Point(0,0),Point(10,0));
L[n++].twoPointIntial(Point(10,0),Point(10,10));
L[n++].twoPointIntial(Point(10,10),Point(0,10));
L[n++].twoPointIntial(Point(0,10),Point(0,0));
np=1;
while(cin>>p[np].x>>p[np].y)
{
cin>>s;
if(s=="Same") zero=1;

Vector v=p[np]-p[np-1];
v=Vector(v.y,-v.x);
Point midP=getMidPoint(p[np],p[np-1]);

if(dcmp(Cross(v,p[np-1]-midP ) )<0 )  v=-v;
if(s=="Hotter")  v=-v;

L[n++]=Line( midP,v);

if(zero)
{
puts("0.00");
}
else
{
int m=HalfplaneIntersection(L,n,poly);
double s=PolygonArea(poly,m);
if(dcmp(s)==0 )  puts("0.00");
else printf("%.2f\n",s);
}
np++;
}
return 0;
}


#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;

#define all(x) (x).begin(), (x).end()
#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)
#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)
#define mes(a,x,s)  memset(a,x,(s)*sizeof a[0])
#define mem(a,x)  memset(a,x,sizeof a)
#define ysk(x)  (1<<(x))
typedef long long ll;
typedef pair<int, int> pii;
const int INF =0x3f3f3f3f;
const int maxn= 100   ;
const double PI=acos(-1.0);
const double eps=1e-10;
int dcmp(double x)
{
if(fabs(x)<eps)  return 0;
else return x<0?-1:1;
}
struct Point
{
double x,y;
Point(double x=0,double y=0):x(x),y(y) {};
bool operator ==(const Point B)const {return dcmp(x-B.x)==0&&dcmp(y-B.y)==0;}

bool operator<(const Point& b)const
{
return dcmp(x-b.x)<0|| dcmp(x-b.x)==0 &&dcmp(y-b.y)<0;
}
};
typedef Point Vector;
Vector operator -(Vector A,Vector B) {return Vector(A.x-B.x,A.y-B.y); }

double Cross(Vector A,Vector B)//叉乘
{
return A.x*B.y-A.y*B.x;
}

double Dot(Vector A,Vector B)//点乘
{
return A.x*B.x+A.y*B.y;
}

Vector operator +(Vector A,Vector B) {return Vector(A.x+B.x,A.y+B.y); }
Vector operator *(Vector A,double p) {return Vector(A.x*p,A.y*p); }
Vector operator /(Vector A,double p) {return Vector(A.x/p,A.y/p); }
Vector operator -(Vector A)  {return  Vector(-A.x,-A.y);}

struct Line
{
Point p,p2;
Vector v;
double ang;
Line(){}
Line(Point a,Vector v):p(a),v(v){ang=atan2(v.y,v.x); }//点线式
void twoPointIntial(Point p,Point p2)//两点式
{
this->p=p;
this->p2=p2;
v=  p2-p;
ang=atan2(v.y,v.x);
}
Point point(double t)//参数方程求参数t对应点
{
return p+v*t;
}
bool operator<(const Line & L)const
{
return ang<L.ang;
}
};

Point GetIntersection(Line a,Line b)
{
Vector u=a.p-b.p;
double t=Cross(b.v,u)/Cross(a.v,b.v);
return a.p+a.v*t;
}

bool OnRight(Line L,Point p)
{
return dcmp(Cross(L.v,p-L.p))<0;
}

int HalfplaneIntersection(Line* L,int n,Point * poly)
{
sort(L,L+n);
int first,last;
Point *p=new Point
;
Line *q=new Line
;
q[first=last=0]=L[0];
for(int i=1;i<n;i++)
{
while(first<last&&OnRight(L[i],p[last-1] ) )  last--;
while(first<last&&OnRight(L[i],p[first]))  first++;
q[++last]=L[i];
if(fabs(Cross(q[last].v,q[last-1].v) )<eps )
{
last--;
if(!OnRight(q[last],L[i].p) )  q[last]=L[i];
}
if(first<last) p[last-1]=GetIntersection(q[last-1],q[last] );
}
while(first<last&&OnRight(q[first],p[last-1])) last--;
if(last-first<=1)  return 0;//小于3个,不存在
p[last]=GetIntersection(q[last],q[first]);

int m=0;
for(int i=first;i<=last;i++) poly[m++]=p[i];
return m;

}

double PolygonArea(Point *p,int n)
{
double area=0;
for(int i=1;i<n-1;i++)
{
area+=Cross(p[i]-p[0],p[i+1]-p[0]);
}
return area/2;
}

Point getMidPoint(Point a,Point b)
{
return Point( (a.x+b.x)/2,(a.y+b.y)/2 );
}
int n,np;
Line L[maxn+10];
Point p[maxn+10],poly[maxn+10];
string s;

int main()
{
std::ios::sync_with_stdio(false);
double x,y;
bool zero=0;n=0;
L[n++].twoPointIntial(Point(0,0),Point(10,0));
L[n++].twoPointIntial(Point(10,0),Point(10,10));
L[n++].twoPointIntial(Point(10,10),Point(0,10));
L[n++].twoPointIntial(Point(0,10),Point(0,0));
np=1;
while(cin>>p[np].x>>p[np].y)
{
cin>>s;
if(s=="Same") zero=1;

Vector v=p[np]-p[np-1];
v=Vector(v.y,-v.x);
Point midP=getMidPoint(p[np],p[np-1]);

if(dcmp(Cross(v,p[np-1]-midP ) )<0 )  v=-v;
if(s=="Hotter")  v=-v;

L[n++]=Line( midP,v);

if(zero)
{
puts("0.00");
}
else
{
int m=HalfplaneIntersection(L,n,poly);
double s=PolygonArea(poly,m);
if(!m||dcmp(s)==0 )  puts("0.00");
else printf("%.2f\n",s);
}
np++;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj 计算几何