POJ 1039 Pipe

题意:一束光线从左端射入钢管,问能到达的最远点的横坐标。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>

using namespace std;
const double INF = 1e20;
const double EPS = 1e-6;
struct cvector
{
    double x,y;
    cvector(double a,double b)
    {
        x=a,y=b;
    }
    cvector() {}
};
cvector operator+(cvector a,cvector b)
{
    return cvector(a.x+b.x,a.y+b.y);
}
cvector operator-(cvector a,cvector b)
{
    return cvector(a.x-b.x,a.y-b.y);
}
cvector operator*(double a,cvector b)
{
    return cvector(a*b.x,a*b.y);
}
double operator*(cvector a,cvector b)
{
    return a.x*b.x+a.y*b.y;
}
double operator^(cvector a,cvector b)
{
    return a.x*b.y-b.x*a.y;
}
double length(double t)
{
    return t<0?-1:t;
}
double length(cvector t)
{
    return sqrt(t*t);
}
struct cpoint
{
    double x,y;
    cpoint(double a,double b)
    {
        x=a,y=b;
    }
    cpoint() {}
};
cvector operator-(cpoint a,cpoint b)
{
    return cvector(a.x-b.x,a.y-b.y);
}
double dist(cpoint a,cpoint b)
{
    return length(a-b);
}
struct cline
{
    cpoint a,b;
};
bool intersect(cline a,cline b)
{
    return ((a.a-b.a)^(b.b-b.a))*((a.b-b.a)^(b.b-b.a))<EPS;
}
cpoint intersection(cline u, cline v)
{
    cpoint ret=u.a;
    double t=((u.a.x-v.a.x)*(v.a.y-v.b.y)-(u.a.y-v.a.y)*(v.a.x-v.b.x))/
             ((u.a.x-u.b.x)*(v.a.y-v.b.y)-(u.a.y-u.b.y)*(v.a.x-v.b.x));
    ret.x+=(u.b.x-u.a.x)*t;
    ret.y+=(u.b.y-u.a.y)*t;
    return ret;
}
cline re[29];
cline edge[29][2];
int n;
double oper(cline tmp)
{
    if(!intersect(re[0],tmp))return -INF;
    double ans = -INF;
    int k;
    for(k=1; k<n; k++)
        if(!intersect(re[k],tmp))
        {
            cpoint x;
            x = intersection(edge[k][0],tmp);
            ans = max(ans,x.x);
            x = intersection(edge[k][1],tmp);
            ans = max(ans,x.x);
            break;
        }
    if(k>=n)return INF;
    return ans;
}
int main()
{
    freopen("in.txt","r",stdin);
    while(scanf("%d",&n)&&n)
    {
        double ans = -INF;
        for(int i=0; i<n; i++)
        {
            scanf("%lf%lf",&re[i].a.x,&re[i].a.y);
            re[i].b.x=re[i].a.x;
            re[i].b.y=re[i].a.y-1;
            if(i)
            {
                edge[i][0].a=re[i].a;
                edge[i][0].b=re[i-1].a;
                edge[i][1].a=re[i].b;
                edge[i][1].b=re[i-1].b;
            }
        }
        cline tmp;
        for(int i=0; i<n&&ans!=INF; i++)
        {
            for(int j=i+1; j<n&&ans!=INF; j++)
            {
                tmp.a=re[i].a,tmp.b=re[j].a;
                ans = max(ans,oper(tmp));
                tmp.a=re[i].b,tmp.b=re[j].b;
                ans = max(ans,oper(tmp));
                tmp.a=re[i].b,tmp.b=re[j].a;
                ans = max(ans,oper(tmp));
                tmp.a=re[i].a,tmp.b=re[j].b;
                ans = max(ans,oper(tmp));
            }
        }
        if(ans==INF) printf("Through all the pipe.\n");
        else printf("%.2lf\n",ans);
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值