首页 > 代码库 > POJ 2540 半平面交求可行区域面积

POJ 2540 半平面交求可行区域面积

Hotter Colder
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 2343 Accepted: 981

Description

The children‘s game Hotter Colder is played as follows. Player A leaves the room while player B hides an object somewhere in the room. Player A re-enters at position (0,0) and then visits various other positions about the room. When player A visits a new position, player B announces "Hotter" if this position is closer to the object than the previous position; player B announces "Colder" if it is farther and "Same" if it is the same distance.

Input

Input consists of up to 50 lines, each containing an x,y coordinate pair followed by "Hotter", "Colder", or "Same". Each pair represents a position within the room, which may be assumed to be a square with opposite corners at (0,0) and (10,10).

Output

For each line of input print a line giving the total area of the region in which the object may have been placed, to 2 decimal places. If there is no such region, output 0.00.

Sample Input

10.0 10.0 Colder
10.0 0.0 Hotter
0.0 0.0 Colder
10.0 10.0 Hotter

Sample Output

50.00
37.50
12.50
0.00


假如出现“same”,以后的答案都为0,因为目标在一条线上,而题目要求的是面积。

否则根据Colder,Hotter判断在哪边,半平面加边每一次求半平面

代码:

/* ***********************************************
Author :_rabbit
Created Time :2014/5/4 15:03:55
File Name :20.cpp
************************************************ */
#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <string>
#include <time.h>
#include <math.h>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
#define INF 10000000
#define eps 1e-8
#define pi acos(-1.0)
typedef long long ll;
int dcmp(double x){
	if(fabs(x)<eps)return 0;
	return x>0?1:-1;
}
struct Point{
	double x,y;
	Point(double _x=0,double _y=0){
		x=_x;y=_y;
	}
};
Point operator + (const Point &a,const Point &b){
	return Point(a.x+b.x,a.y+b.y);
}
Point operator - (const Point &a,const Point &b){
	return Point(a.x-b.x,a.y-b.y);
}
Point operator * (const Point &a,const double &p){
	return Point(a.x*p,a.y*p);
}
Point operator / (const Point &a,const double &p){
	return Point(a.x/p,a.y/p);
}
bool operator < (const Point &a,const Point &b){
	return a.x<b.x||(a.x==b.x&&a.y<b.y);
}
bool operator == (const Point &a,const Point &b){
	return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}
double Dot(Point  a,Point b){
	return a.x*b.x+a.y*b.y;
}
double Length(Point a){
	return sqrt(Dot(a,a));
}
double Angle(Point a,Point b){
	return acos(Dot(a,b)/Length(a)/Length(b));
}
double angle(Point a){
	return atan2(a.y,a.x);
}
double Cross(Point a,Point b){
	return a.x*b.y-a.y*b.x;
}
Point vecunit(Point a){
	return a/Length(a);
}
Point Normal(Point a){
	return Point(-a.y,a.x)/Length(a);
}
Point Rotate(Point a,double rad){
	return Point(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));
}
double Area2(Point a,Point b,Point c){
	return Length(Cross(b-a,c-a));
}
struct Line{
	Point p,v;
	double ang;
	Line(){};
	Line(Point p,Point v):p(p),v(v){
		ang=atan2(v.y,v.x);
	}
	bool operator < (const Line &L) const {
		return ang<L.ang;
	}
};
bool OnLeft(const Line &L,const Point &p){
	return dcmp(Cross(L.v,p-L.p))>=0;
}
Point GetLineIntersection(Point p,Point v,Point q,Point w){
	Point u=p-q;
	double t=Cross(w,u)/Cross(v,w);
	return p+v*t;
}
Point GetLineIntersection(Line a,Line b){
	return GetLineIntersection(a.p,a.v,b.p,b.v);
}
vector<Point> HPI(vector<Line> L){
	int n=L.size();
	sort(L.begin(),L.end());//将所有半平面按照极角排序。
	/*for(int i=0;i<n;i++){
		cout<<"han  "<<i<<" ";
		printf("%.2lf  %.2lf  %.2lf  %.2lf  %.2lf\n",L[i].p.x,L[i].p.y,L[i].v.x,L[i].v.y,L[i].ang);
	}*/
	int first,last;
	vector<Point> p(n);
	vector<Line> q(n);
	vector<Point> ans;
	q[first=last=0]=L[0];
	for(int i=1;i<n;i++){
		while(first<last&&!OnLeft(L[i],p[last-1]))last--;//删除顶部的半平面
		while(first<last&&!OnLeft(L[i],p[first]))first++;//删除底部的半平面
		q[++last]=L[i];//将当前的半平面假如双端队列顶部。
		if(fabs(Cross(q[last].v,q[last-1].v))<eps){//对于极角相同的,选择性保留一个。
			last--;
			if(OnLeft(q[last],L[i].p))q[last]=L[i];
		}
		if(first<last)p[last-1]=GetLineIntersection(q[last-1],q[last]);//计算队列顶部半平面交点。
	}
	while(first<last&&!OnLeft(q[first],p[last-1]))last--;//删除队列顶部的无用半平面。
	if(last-first<=1)return ans;//半平面退化
	p[last]=GetLineIntersection(q[last],q[first]);//计算队列顶部与首部的交点。
	for(int i=first;i<=last;i++)ans.push_back(p[i]);//将队列中的点复制。
	return ans;
}
double PolyArea(vector<Point> p){
	int n=p.size();
	double ans=0;
	for(int i=1;i<n-1;i++)
		ans+=Cross(p[i]-p[0],p[i+1]-p[0]);
	return fabs(ans)/2;
}
Point pp[200];
int main()
{
     //freopen("data.in","r",stdin);
     //freopen("data.out","w",stdout);
	Point a,b;
	vector<Line> L;
    Line s;
	a=Point(0,0);b=Point(10,0);s=Line(a,b-a);L.push_back(s);
	a=Point(10,0);b=Point(10,10);s=Line(a,b-a);L.push_back(s);
	a=Point(10,10);b=Point(0,10);s=Line(a,b-a);L.push_back(s);
	a=Point(0,10);b=Point(0,0);s=Line(a,b-a);L.push_back(s);
	Point pre,cur;
	char str[100];
	int flag=0;
	while(~scanf("%lf%lf%s",&cur.x,&cur.y,str)){
		if(flag)puts("0.00");
		else{
			if(str[0]==‘S‘){
				flag=1;
				puts("0.00");
			}
			else{
				a=(pre+cur)/2;
				b=Normal(cur-pre);
				if(str[0]==‘C‘)L.push_back(Line(a,b));
				if(str[0]==‘H‘)L.push_back(Line(a,Point(-b.x,-b.y)));
				vector<Point> ans=HPI(L);
				printf("%.2f\n",PolyArea(ans));
				pre=cur;
			}
		}
	}
     return 0;
}