【计算几何】POJ1039 Pipe

题面在这里

这是我A的第一道真正意义上的计算几何题……
一开始想法不好,重写了两次,花了两个半天才A掉……各位见笑了

题意大致如下:给定一根由上下两条折线构成的管道(上下壁均不透明、不反光),求光线是否能穿过管道,或输出最远能到的距离。

那么有这样一个推论:最优的线路一定经过上端点、下端点至少各一个。因为若光线不经过任何端点,就完全可以旋转、平移它,使其射得更远,那么经过端点就是移动的极端情况,就有可能最优。
于是可以直接枚举上下两个端点,引一条直线,依次判断是否穿过每个弯的间隔(我们把x坐标相同的一对端点之间的线段称为间隔)若穿过所有间隔就输出,否则还要更新最远距离

贴个代码:

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=25;
const double eps=1e-4;
int n;
struct point{
    double x,y;
    point(double x=0,double y=0):x(x),y(y) {}
}a[maxn],b[maxn];
struct line{
    double k,b;
    void get(point x,point y){
        k=(x.y-y.y)/(x.x-y.x);
        b=x.y-k*x.x;
    }
    double gety(double x){return k*x+b;}
}l[45];
int dcmp(double a,double b){
    if (fabs(a-b)<eps) return 0;
    if (a<b) return -1;
    return  1;
}
double intersect(line a,line b){
    return (b.b-a.b)/(a.k-b.k);
}
int main(){
    scanf("%d",&n);
    while (n){
        for (int i=1;i<=n;i++){
            double x,y;scanf("%lf%lf",&x,&y);
            a[i]=point(x,y);b[i]=point(x,y-1);
            if (i>1){
                l[i*2-1].get(a[i],a[i-1]);
                l[i*2].get(b[i],b[i-1]);
            }
        }
        double ans=-(1e100);bool flg=0;
        for (int i=1;i<=n&&!flg;i++)
         for (int j=1;j<=n&&!flg;j++)
          if (i!=j){
            line now;now.get(a[i],b[j]);int k;
            for (k=1;k<=n;k++){
                double y=now.gety(a[k].x);
                if (!(dcmp(b[k].y,y)<=0&&dcmp(y,a[k].y)<=0)) break;
            }
            if (k>n) {flg=1;break;}
            if (k<=max(i,j)) continue;
            ans=max(ans,max(intersect(now,l[k*2-1]),intersect(now,l[k*2])));
          }
        if (flg) printf("Through all the pipe.\n");else printf("%.2f\n",ans);
        scanf("%d",&n);
    }
    return 0;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值