poj 1039 Pipe

《算法艺术与信息学竞赛》p356例题,自己没做对,看了下题解,还是考虑的地方太少了。
题解:http://blog.csdn.net/lyy289065406/article/details/6648585
思路:
这里写图片描述

#include <cmath>
#include <cstring>
#include <cstdio>

struct Point
{
    double x,y;
};
const double precision = 1e-8;
const double inf = 9999999.0;
Point upperPoint[25];
Point lowerPoint[25];
double res;
bool flag;
int n;

int max(int a, int b)
{
    return a > b ? a : b;
}

int dblcmp(double d)//精度
{
    if(fabs(d) < precision)
        return 0;
    return d < 0 ? -1 : 1;
}

double det(double x1, double y1, double x2, double y2)
{
    return x1*y2 - x2*y1;
}
//求ab和ac叉积
double cross(Point a, Point b, Point c)
{
    return det(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);
}

//如果ab和cd相交,返回true
bool check(Point a, Point b, Point c, Point d)
{
    return dblcmp(cross(a,b,c))*dblcmp(cross(a,b,d)) <= 0;
}

double intersection(Point A, Point B, Point C, Point D)
{
    double area1 = cross(A,B,C);
    double area2 = cross(A,B,D);
    int c = dblcmp(area1);
    int d = dblcmp(area2);
    //规范相交
    if(c*d < 0)
        return (area2*C.x - area1*D.x) / (area2 - area1);//叉积求交点,黑书上有
    //非规范相交
    if(c*d == 0)
    {
        if(c == 0)
            return C.x;
        else
            return D.x;
    }
    return -inf;
}

void solve(int i, int j)
{
    int k;
    for(k = 1; k <= n; ++k)
    {
        if(!check(upperPoint[i],lowerPoint[j],upperPoint[k],lowerPoint[k]))
            break;
    }
    //通过所有管道
    if(k > n)
    {
        flag = true;
        return;
    }
    //撞到管道壁上了 k要大于i,j才可以,如果小于i,j,光线就进不来这个管道了
    else if(k > max(i,j))
    {
        double temp = intersection(upperPoint[i],lowerPoint[j],upperPoint[k],upperPoint[k-1]);
        if(res < temp) res = temp;
        temp = intersection(upperPoint[i],lowerPoint[j],lowerPoint[k],lowerPoint[k-1]);
        if(res < temp) res = temp;
    }
}

int main()
{
    while(scanf("%d",&n) && n)
    {
        res = -inf;
        flag = false;
        for(int i = 1; i <= n; ++i)
        {
            scanf("%lf %lf",&upperPoint[i].x,&upperPoint[i].y);
            lowerPoint[i].x = upperPoint[i].x;
            lowerPoint[i].y = upperPoint[i].y - 1.0;
        }

        for(int i = 1; i <= n; ++i)
        {
            for(int j = 1; j <= n; ++j)
            {
                if(i != j)
                    solve(i,j);
            }
            if(flag) break;
        }
        if(flag) printf("Through all the pipe.\n");
        else printf("%.2f\n",res);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值