poj 2540 Hotter Colder(线性规划可行区域)

Hotter Colder
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 1836 Accepted: 764

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

Source

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

题意:两个人玩藏东西,一个藏,一个找,屋子的大小事0,0 到 10,10,的正方形,从0,0开始找,每次都会提示比前一次近还是远,问每次的可能在的区域大小

分析:每次比前一次近或远或相等,相等的话,面积必然是0,那么就剩下不等的,沿着前后两点做垂直平分线,平分线的方程,远了就让它小于0,近了则相反,这样就转换成求线性规划的可行区域大小,可以用半平面交来做,记得加上屋子那四个半平面,好不容易又一题1Y,这几次让精度问题整怕了T_T

代码:

#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int mm=111;
const double eps=1e-8;
typedef double diy;
struct point
{
    diy x,y;
    point(){}
    point(diy _x,diy _y):x(_x),y(_y){}
}g[mm];
point Vector(point s,point t)
{
    return point(t.x-s.x,t.y-s.y);
}
diy CrossProduct(point P,point Q)
{
    return P.x*Q.y-P.y*Q.x;
}
diy MultiCross(point P,point Q,point R)
{
    return CrossProduct(Vector(Q,P),Vector(Q,R));
}
struct halfPlane
{
    point s,t;
    diy angle;
    halfPlane(){}
    halfPlane(point _s,point _t){s=_s,t=_t,angle=atan2(t.y-s.y,t.x-s.x);}
}hp[mm],q[mm];
point Intersection(halfPlane P,halfPlane Q)
{
    diy a1=CrossProduct(Vector(P.s,Q.t),Vector(P.s,Q.s));
    diy a2=CrossProduct(Vector(P.t,Q.s),Vector(P.t,Q.t));
    return point((P.s.x*a2+P.t.x*a1)/(a1+a2),(P.s.y*a2+P.t.y*a1)/(a1+a2));
}
halfPlane MakeHP(diy a,diy b,diy c)
{
    if(fabs(a)<eps)
        return halfPlane(point(b<0?-1:1,-c/b),point(b<0?1:-1,-c/b));
    if(fabs(b)<eps)
        return halfPlane(point(-c/a,a<0?1:-1),point(-c/a,a<0?-1:1));
    if(b<0)return halfPlane(point(0,-c/b),point(1,-(a+c)/b));
    return halfPlane(point(1,-(a+c)/b),point(0,-c/b));
}
bool IsParallel(halfPlane P,halfPlane Q)
{
    return fabs(CrossProduct(Vector(P.s,P.t),Vector(Q.s,Q.t)))<eps;
}
bool cmp(halfPlane P,halfPlane Q)
{
    if(fabs(P.angle-Q.angle)<eps)
        return MultiCross(P.s,P.t,Q.s)>0;
    return P.angle<Q.angle;
}
void HalfPlaneIntersect(int &n,int &m)
{
    sort(hp,hp+n,cmp);
    int i,l=0,r=1;
    for(m=i=1;i<n;++i)
        if(hp[i].angle-hp[i-1].angle>eps)hp[m++]=hp[i];
    n=m,m=0;
    q[0]=hp[0],q[1]=hp[1];
    for(i=2;i<n;++i)
    {
        if(IsParallel(q[r],q[r-1])||IsParallel(q[l],q[l+1]))break;
        while(l<r&&MultiCross(hp[i].s,hp[i].t,Intersection(q[r],q[r-1]))>0)--r;
        while(l<r&&MultiCross(hp[i].s,hp[i].t,Intersection(q[l],q[l+1]))>0)++l;
        q[++r]=hp[i];
    }
    while(l<r&&MultiCross(q[l].s,q[l].t,Intersection(q[r],q[r-1]))>0)--r;
    while(l<r&&MultiCross(q[r].s,q[r].t,Intersection(q[l],q[l+1]))>0)++l;
    q[++r]=q[l];
    for(i=l;i<r;++i)
        g[m++]=Intersection(q[i],q[i+1]);
}
int main()
{
    char sta[9];
    diy sx=0,sy=0,tx,ty,a,b,c,ans;
    int i,n=0,m,flag=1;
    hp[n++]=halfPlane(point(0,0),point(10,0));
    hp[n++]=halfPlane(point(10,0),point(10,10));
    hp[n++]=halfPlane(point(10,10),point(0,10));
    hp[n++]=halfPlane(point(0,10),point(0,0));
    while(~scanf("%lf%lf%s",&tx,&ty,sta))
    {
        a=sx-tx;
        b=sy-ty;
        c=-(a*(sx+tx)+b*(sy+ty))/2;
        if(sta[0]=='H')hp[n++]=MakeHP(a,b,c);
        if(sta[0]=='C')hp[n++]=MakeHP(-a,-b,-c);
        if(sta[0]=='S')flag=0;
        ans=0;
        if(flag)
        {
            HalfPlaneIntersect(n,m);
            if(m>2)
            {
                g[m]=g[0];
                for(i=0;i<m;++i)
                    ans+=CrossProduct(g[i],g[i+1]);
            }
        }
        if(ans<0)ans=-ans;
        printf("%.2lf\n",ans/2);
        sx=tx,sy=ty;
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值