POJ 2540 Hotter Colder(半平面交)

题目链接:http://poj.org/problem?id=2540

题意:一个正方形,坐标为(0,0)、(10,0)、(10、10)、(0,10)。现在有A、B两人做一个游戏。B首先指定一个正方形中的目标位置P。开始时A在(0,0)点,每次A走到另一点上,B告诉A离目标位置远了(Colder)还是近了(Hotter)还是一样(Same),在B每次告诉A后输出目标位置可能的面积。

思路:每次走过的路线的中垂线和原多边形求交。根据Colder和Hotter判断是交左侧还是右侧。



int DB(double x)
{
    if(x>1e-10) return 1;
    if(x<-1e-10) return -1;
    return 0;
}

struct point
{
    double x,y;

    point(){}
    point(double _x,double _y)
    {
        x=_x;
        y=_y;
    }

    void read()
    {
        RD(x,y);
    }

    void output()
    {
        printf("(%.2lf %.2lf)",x,y);
    }

    point operator+(point a)
    {
        return point(x+a.x,y+a.y);
    }
    point operator-(point a)
    {
        return point(x-a.x,y-a.y);
    }

    double operator*(point a)
    {
        return x*a.y-y*a.x;
    }

    point operator*(double t)
    {
        return point(x*t,y*t);
    }

    point operator/(double t)
    {
        return point(x/t,y/t);
    }

    bool operator==(point a)
    {
        return DB(x-a.x)==0&&DB(y-a.y)==0;
    }

    bool operator!=(point a)
    {
        return DB(x-a.x)||DB(y-a.y);
    }
};


point a[N];
int n;


//t在ab的左侧返回正值
double cross(point a,point b,point t)
{
    return point(b-a)*point(t-a);
}


point getCross(point a,point b,point p,point q)
{
    double s1=(a-p)*(b-p);
    double s2=(b-q)*(a-q);
    double t=s1+s2;
    return (p*s2+q*s1)/(s1+s2);
}

double getDist(point a,point b)
{
    return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}

double getArea(point p[],int n)
{
    double ans=0;
    int i;
    p[n]=p[0];
    FOR0(i,n) ans+=p[i]*p[i+1];
    return ans/2;
}

void moveSegment(point &p1,point &p2,double r)
{
    r/=getDist(p1,p2);
    point p=point(p1.y-p2.y,p2.x-p1.x)*r;
    p1=p1+p;
    p2=p2+p;
}

void deal(point a[],int &n,point p1,point p2,int flag)
{
    point b[N],p;
    int i,m=n,t1,t2;
    FOR0(i,n) b[i]=a[i];
    b[m]=b[0];
    n=0;
    FOR0(i,m)
    {
        t1=DB(cross(p1,p2,b[i]));
        t2=DB(cross(p1,p2,b[i+1]));
        p=getCross(p1,p2,b[i],b[i+1]);
        if(flag) t1=-t1,t2=-t2;
        if(t1>0&&!t2||t1>0&&t2>0||!t1&&t2>0)
        {
            a[n++]=b[i],a[n++]=b[i+1];
        }
        else if(t1>0&&t2<0) a[n++]=b[i],a[n++]=p;
        else if(t1<0&&t2>0) a[n++]=p,a[n++]=b[i+1];
        else if(!t1&&t2<0) a[n++]=b[i];
        else if(t1<0&&!t2) a[n++]=b[i+1];
    }
    m=1;
    FOR1(i,n-1) if(a[i]!=a[i-1]) a[m++]=a[i];
    if(a[m-1]==a[0]) m--;
    n=m;
}

void deal(point a[],int &n,point p1,point p2,char cmd[])
{
    point mid=(p1+p2)/2,dir=point(p1.y-p2.y,p2.x-p1.x);
    deal(a,n,mid,mid+dir,cmd[0]=='H');
}

int main()
{
    point pre=point(0,0),cur;
    char cmd[20];
    int flag=0;
    a[0]=point(0,0);
    a[1]=point(10,0);
    a[2]=point(10,10);
    a[3]=point(0,10);
    n=4;
    while(scanf("%lf%lf%s",&cur.x,&cur.y,cmd)!=-1)
    {
        if(cmd[0]=='S'||flag)
        {
            puts("0.00");
            flag=1;
            continue;
        }
        deal(a,n,pre,cur,cmd);
        printf("%.2lf\n",fabs(getArea(a,n)));
        pre=cur;
    }
    return 0;
}

  

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值