[POJ2826]An Easy Problem?!(计算几何-细节/距离)

题目:

我是超链接

题意:

给出两条线段,雨水从空中竖直落下,问线段上能积多少水。

题解:

一道特判超~~~多的题目,下见注释咯
这道题精度会有-0.00?!加个fabs吧。

这题的题解。。。真是敷衍啊
那就加个对于距离的讲解吧,虽然这个题没有用
点到直线的距离(用面积法啦)【如果a旋转到b是逆时针,则叉积为正,否则叉积为负】

double DisDL(Point P,Point A,Point B)
{
    Vector v=B-A,w=P-A;
    return fabs(Cross(v,w)/Len(v));
}

点到线段的距离?如果做垂直能在直线上,那就是点到直线的距离,否则就是到某个端点的距离
用点积做比较简单【如果a b夹角大于90度,点积为负,小于90度,点积为正】

double DisTS(Point P,Point A,Point B)
{
    if (A==B) return Len(P-A);
    Vector v=B-A,w=P-A,u=P-B;
    if (dcmp(Dot(v,w))<0) return Len(w);
    else if (dcmp(Dot(v,u))>0) return Len(u);
    else return fabs(Cross(v,w)/Len(v));
}

上面就是关于距离的基本知识

代码:

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const double eps=1e-9;
int dcmp(double x)
{
    if (x<=eps && x>=-eps) return 0;
    return (x>0)?1:-1;
}
struct po
{
    double x,y;
    po(double X=0,double Y=0){x=X;y=Y;}
};
po operator +(po x,po y){return po(x.x+y.x,x.y+y.y);}
po operator -(po x,po y){return po(x.x-y.x,x.y-y.y);}
po operator *(po x,double y){return po(x.x*y,x.y*y);}
double dj(po x,po y){return x.x*y.x+x.y*y.y;}
double cj(po x,po y){return x.x*y.y-x.y*y.x;}
double len(po x){return sqrt(dj(x,x));}
bool jd(po a,po b,po c,po d)//有交点且不重合 
{
    double d1=dcmp(cj(c-a,b-a)),d2=dcmp(cj(d-a,b-a));
    double d3=dcmp(cj(a-d,c-d)),d4=dcmp(cj(b-d,c-d));
    return d1!=d2 && d3!=d4;
}
po dd(po a,po b,po c,po d)//交点坐标
{
    po A=a-c,B=b-a,D=d-c;
    double t=cj(D,A)/cj(B,D);
    return a+B*t;
}
int main()
{
    int T;scanf("%d",&T);
    while (T--)
    {
        double x1,y1,x2,y2,x3,y3,x4,y4,dis=0;
        scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
        po a=po(x1,y1),b=po(x2,y2),c=po(x3,y3),d=po(x4,y4);
        if (!jd(a,b,c,d)) {printf("0.00\n");continue;}//没有交点|重合 
        if (y1==y2 || y3==y4){printf("0.00\n");continue;} //平的肯定接不住水啊 
        if (y1>y2) swap(a,b);
        if (y3>y4) swap(c,d);//b,d头在上 
        po now=dd(a,b,c,d);
        double h=min(b.y-now.y,d.y-now.y);
        if (dcmp(h)<=0) {printf("0.00\n");continue;}
        if (b.y<d.y) swap(b,d),swap(a,c);//a,b线段在上 
        if (a.x!=b.x) 
        {
            double k1=(b.y-a.y)/(b.x-a.x);
            double k2=(d.y-c.y)/(d.x-c.x);
            if (k1*k2>0 && ((dcmp(k1)<0 && b.x<=d.x && dcmp(k1-k2)<0) || (dcmp(k1)>0 && b.x>=d.x && dcmp(k1-k2)>0))) {printf("0.00\n");continue;}
            //斜率一正一负肯定接的到水,两正|负就要看看上面那个能不能完全挡住下面那个
            double b1=a.y-k1*a.x;
            double xd=(d.y-b1)/k1;
            dis=fabs(d.x-xd);
        }else dis=fabs(d.x-b.x);
        printf("%.2lf\n",fabs(dis*h/2));
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值