poj 2540 Hotter Colder

本文详细介绍了半平面交算法的实现细节,包括如何通过不断进行半平面交来求解问题,特别关注中垂线方向的处理及特殊情况的判断。文中还提供了一个具体的代码示例,演示了算法的具体操作流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

做法:不断的去半平面交

注意点:中垂线的方向,我用的是逆时针边界,当为same时,解在中垂线上,输出0,而且只要有一次输出为0,以后的输出都会为0;

这个题又学到了一个向量旋转的函数。。不错不错~~~~大笑

#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const double pi=acos(-1.0);
const double eps=1e-8;
int n,ln,dq[1000000],top,bot,pn,ln2;
double area; 
struct P
{
	double x,y;
	P(){}
	P(double x,double y):x(x),y(y){
	}
	P operator +(P p){
		return P(x+p.x,y+p.y);
	}
	P operator -(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);
	}
	double det(P p){
		return x*p.y-y*p.x;
	}
}p[100000];
struct Line
{
	P a,b;
	double angle;
}l[1000000],l1[1000000];
P in(Line a,Line b)
{
	return a.a+(a.b-a.a)*((b.b-b.a).det(b.a-a.a)/(b.b-b.a).det(a.b-a.a));
}
int dblcmp(double k)
{
	if(fabs(k)<eps)
		return 0;
	return k>0?1:-1;
}
bool cmp(Line a,Line b)
{
	int d=dblcmp(a.angle-b.angle);
	if(!d)
		return dblcmp((b.a-a.a).det(b.b-a.a))>0;
	return d<0;
}
bool judge(Line a,Line b,Line c)
{
	P r=in(b,c);
	return dblcmp((a.a-r).det(a.b-r))<0;
}
P A,B;
char s[1000000];
void HPI()
{
	int i,j;
	for( i=0;i<ln;i++)
		l1[i]=l[i];
	sort(l1,l1+ln,cmp);
	int len;
	for(i=0,j=0;i<ln;i++)
	{
		if(dblcmp(l1[i].angle-l1[j].angle)>0)
			l1[++j]=l1[i];
	}

	len=j+1;
	top=1;
	bot=0;
	dq[0]=0;
	dq[1]=1;
	for(i=2;i<len;i++)
	{
		while(top>bot && judge(l1[i],l1[dq[top]],l1[dq[top-1]])) top--;
		while(top>bot && judge(l1[i],l1[dq[bot]],l1[dq[bot+1]])) bot++;
		dq[++top]=i;
	}
	while(top>bot && judge(l1[dq[bot]],l1[dq[top]],l1[dq[top-1]])) top--;
	while(top>bot && judge(l1[dq[top]],l1[dq[bot]],l1[dq[bot+1]])) bot++;
	dq[++top]=dq[bot];
	for(i=bot,pn=0;i<top;i++,pn++)
	{
		p[pn]=in(l1[dq[i]],l1[dq[i+1]]);
	}
}
void getarea()
{
	if(pn<3)
	{
		area=0;
	}
	else
	{
		for(int i=1;i<pn-1;i++)
		{
			area+=(p[i]-p[0]).det(p[i+1]-p[0]);
		}
		area=fabs(area);
		area/=2.0;
	}
}
//向量的旋转 //底边线段ab 绕a逆时针旋转角度A,b->b1,sinl是sinA的值。 
P Whirl(double cosl, double sinl, P a, P b)
{    
	b.x -= a.x; b.y -= a.y;
	P c;
	c.x = b.x * cosl - b.y * sinl + a.x;
	c.y = b.x * sinl + b.y * cosl + a.y;
	return c;
}
int main()
{
	A.x=0;
	A.y=0;
	ln=0;

	l[ln].a.x=0;l[ln].a.y=0;l[ln].b.x=10;l[ln].b.y=0;
	l[ln].angle=atan2(l[ln].b.y-l[ln].a.y,l[ln].b.x-l[ln].a.x);
	ln++;

	l[ln].a.x=10;l[ln].a.y=0;l[ln].b.x=10;l[ln].b.y=10;
	l[ln].angle=atan2(l[ln].b.y - l[ln].a.y,l[ln].b.x-l[ln].a.x);
	ln++;

	l[ln].a.x=10;l[ln].a.y=10;l[ln].b.x=0;l[ln].b.y=10;
	l[ln].angle=atan2(l[ln].b.y-l[ln].a.y,l[ln].b.x-l[ln].a.x);
	ln++;

	l[ln].a.x=0;l[ln].a.y=10;l[ln].b.x=0;l[ln].b.y=0;
	l[ln].angle=atan2(l[ln].b.y-l[ln].a.y,l[ln].b.x-l[ln].a.x);
	ln++;
	int flag=0;
	while(~scanf("%lf %lf %s",&B.x,&B.y,s))
	{
		P C=(A+B)/2.0;
		area=0;
		A=B;
		if(s[0]=='H')
		{
			
			l[ln].a=C;l[ln].b=Whirl(0,-1,C,B);
			l[ln].angle=atan2(l[ln].b.y-l[ln].a.y,l[ln].b.x-l[ln].a.x);
			ln++;
		}
		else if(s[0]=='C')
		{
			l[ln].a=C;l[ln].b=Whirl(0,1,C,B);
			l[ln].angle=atan2(l[ln].b.y-l[ln].a.y,l[ln].b.x-l[ln].a.x);
			ln++;
		}
		else
		{
			flag=1;
		}
		if(flag)
			printf("0.00\n");
		else
		{
			HPI();
			getarea();
			printf("%.2lf\n",area);
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值