uva 303 pipe (求线段交点,判断线段相交)

这题并不难,但我却弄了一天。

只要枚举每个上面的点与下面的点的连线,在看这条线能到达的最远的地方。

然后如果这条线与上面或下面的第i条斜线线相交的话,必然会相交与up[i]-down[i]这条垂线相交。

这题找错找了很久,找了各种各样的错。最后还是看了别人的代码才发现算法上出现了问题。

所以以后找错一定要想算法是否错了。

代码:


#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#define MAXN 100
#define ESP 1e-8
#define MAXNUM 1e8
struct point    
{
    double x,y;
    point(double _x=0,double _y=0) : x(_x),y(_y) {};
    void input() { scanf("%lf%lf",&x,&y); }
};
double sgn(double d)
{  return d > ESP ? 1 : (d < -ESP ? -1 : 0);
}
point operator-(const point &p1,const point &p2)    
{  return point(p1.x - p2.x, p1.y - p2.y);
}
double operator*(const point &p1,const point &p2)    
{  return p1.x*p2.y - p2.x*p1.y;
}
double operator==(const point &p1,const point &p2)
{
    return sgn(p1.x-p2.x)==0 && sgn(p1.y-p2.y)==0;
}

double min(double a,double b) { if(a<b) return a; else return b; }
double max(double a,double b) { if(a>b) return a; else return b; }
int n;
point up[MAXN],down[MAXN];
void init()
{
    int i,j,k,r,w;
    for(i=1;i<=n;i++)
    {
        up[i].input();
        down[i].x = up[i].x;
        down[i].y = up[i].y-1;
    }
}
bool jiaodian(point a,point b,point c,point d,point &e)
{
    double d1 = (b-a) * (c-a), d2 = (b-a) * (d-a),
           d3 = (d-c) * (a-c), d4 = (d-c) * (b-c);
    if(sgn(d1)*sgn(d2) > 0)
       return false;
    e = point( (c.x*d2 - d.x*d1) / (d2-d1) , 
               (c.y*d2 - d.y*d1) / (d2-d1) );
    return true;   
}

double fun(point a,point b)
{
    int i,j;
    point c,p1,p2;
    double k,r,w,x1,x2;
    
    x1 = x2 = MAXNUM;
    for(i=1;i<=n;i++)
      if( !jiaodian(a,b,up[i],down[i],c) )  
      {  
         if(i == 1) return up[1].x;
         jiaodian(a,b,up[i],up[i-1],c);
         x1 = c.x;
         jiaodian(a,b,down[i],down[i-1],c);
         x2 = c.x;
        
         return max(x1,x2);
      }
   // printf("\n");
   
    return up[n].x;
}

void solve()
{
    int i,j,k,r,w;
    point a;
    double ans=-1e8;
    
    ans = up[1].x;
    for(i=1;i<=n;i++)
      for(j=1;j<=n;j++)    
        if(i != j) 
        {  
           ans = max(ans, fun(up[i],down[j]) );
          // printf("%d %d %f\n",i,j,fun(up[i],down[j]));
        }   
    if(sgn(ans-up[n].x) < 0) printf("%.2f\n",ans);
    else printf("Through all the pipe.\n");
        
}
int main()
{
    //freopen("p303.in","r",stdin);
    while(scanf("%d",&n) != EOF && n)
    {
        init();
        solve();
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值