uva 10084 - Hotter Colder(半平面交)

题目:Hotter Colder

题意:在一个左下角(0,0)右上角(10,10)的正方形里,有个东西藏在里面,一开始主角站在(0,0)点,然后他可以选择移动到(x,y)点,这时如果新点比旧点更接近目标,则得到“Hotter",更远则"Colder",距离一样则是”Same",然后这个(x,y)作为旧点继续重复上述移动,每次移动后输出目标可能存在的区域的面积,如果不存在这样的面积输出0.00。


比较简单的半平面交问题,通过给出的信息不断切割目标范围。

假设原先的点是p0,到达的点是p1,那么可以先求出线段p0p1的中垂线,那么在这条线上的点就是到p0和p1距离一样。反过来如果说得到的是”Same",说明目标范围就是一条线,线的面积是0。。。后面不用算了,全部输出0即可。

求出中垂线的话,这个中垂线可以用点和向量表示,那么我们就可以通过远近的情况确定出目标式在这个向量的左边还是右边,如果是右边还要转个方向,因为半平面交是保留左边的。利用这条线切割原先的区域就可以得到新的区域,然后就是简单算面积了。


PS:各种SB错误本地就调了1个钟,幸好交上去1Y。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
#define pb push_back
const double eps = 1e-8;
int dcmp(double x){
	if(fabs(x)<eps)	return 0;
	return x<0?-1:1;
}
struct Point{
	double x, y;
	Point(){}
	Point(double x, double y):x(x),y(y){}
	bool operator < (const Point &tmp)const{
		return x<tmp.x || (dcmp(x-tmp.x)==0 && y<tmp.y);
	}
};
typedef Point Vector;
Vector operator + (Vector A, Vector B){
	return Vector(A.x+B.x, A.y+B.y);
}
Vector operator - (Point A, Point 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 Rev(Vector A){
	return Vector(-A.y, A.x);
}
Point Mid(Point A, Point B){
	return Point((A.x+B.x)*0.5, (A.y+B.y)*0.5);
}
double dot(Vector A, Vector B){
	return A.x*B.x + A.y*B.y;
}
double det(Vector A, Vector B){
	return A.x*B.y - A.y*B.x;
}
struct Line{
	Point P;
	Vector v;
	Line(){}
	Line(Point P, Vector v):P(P),v(v){}
};
bool OnLeft(Line l, Point p){
	return det(l.v, p-l.P) > 0;
}
typedef vector<Point> Polygon;
Polygon init(){
	Polygon p;
	p.pb(Point(0.0, 0.0));
	p.pb(Point(10.0, 0.0));
	p.pb(Point(10.0, 10.0));
	p.pb(Point(0.0, 10.0));
	return p;
}
Point GetIntersection(Point A, Vector v, Point B, Vector w){
	Vector u = A-B;
	double t = det(w, u)/det(v, w);
	return A+v*t;
}
bool OnSegment(Point P, Point A, Point B){
	return dcmp(det(A-P, B-P))==0 && dcmp(dot(A-P, B-P))<0;
}
double Area(Polygon &p){
	double S = 0.0;
	if(p.size()<=1)	return 0.0;
	for(int i=1; i<p.size()-1; i++){
		S += det(p[i]-p[0], p[i+1]-p[0]);
	}
	return fabs(S)*0.5;
}
Polygon Cut(Polygon p, Line L){
	Polygon newpoly;
	int n = p.size();
//	printf("A: %.2lf %.2lf\n", L.P.x, L.P.y);
//	printf("B-A: %.2lf %.2lf\n", L.v.x, L.v.y);
	for(int i=0; i<n; i++){
		Point C = p[i];
		Point D = p[(i+1)%n];
		if(dcmp(det(L.v, C-L.P)) >= 0)	newpoly.pb(C);
		if(dcmp(det(L.v, C-D)) != 0){
			Point ip = GetIntersection(L.P, L.v, C, D-C);
			if(OnSegment(ip, C, D)){
				newpoly.pb(ip);
			}
		}
	}
	/*
	puts("new");
	for(int i=0; i<newpoly.size(); i++)	printf("%.2lf %.2lf\n", newpoly[i].x, newpoly[i].y);
	puts("end");
	*/
	return newpoly;
}
bool Same(Point A, Point B){
	return dcmp(A.x-B.x)==0 && dcmp(A.y-B.y)==0;
}
int main(){
	Polygon p = init();
	double x, y;
	char s[10];
	bool flag = 0;
	Point p0 = Point(0.0, 0.0);
	Point p1;
	while(~scanf("%lf %lf %s", &x, &y, s)){
		if(s[0]=='S'){
			flag = 1;
		}
		if(flag){
			puts("0.00");
			continue;
		}
		p1 = Point(x, y);
		if(Same(p0, p1)){
			//这里矛盾,因为如果p0和p1相同,上面应该是Same。
			flag = 1;
			puts("0.00");
			continue;
		}
//		printf("%.2lf %.2lf -- %.2lf %.2lf\n", p0.x, p0.y, p1.x, p1.y);
		Vector v = Rev(p1-p0);//求出中位线的向量
		Line L = Line(Mid(p0, p1), v);
		if(OnLeft(L, p0)){
			if(s[0]=='H'){
				L.v = L.v*(-1.0);
			}
		}
		else{
			if(s[0]=='C'){
				L.v = L.v*(-1.0);
			}
		}
		p = Cut(p, L);
		double S = Area(p);
		printf("%.2lf\n", S);
		p0 = p1;
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值