An Easy Problem?! - POJ 2826(求面积)

题目大意:有两块木板交叉起来接雨水,问最多能接多少。
 
分析:题目描述很简单,不过有些细节还是需要注意到,如下图几种情况:
 
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
using namespace std;

const int MAXN = 107;
const double oo = 1e4+7;
const double EPS = 1e-8;

int sign(double val)
{
    if(val > EPS)return 1;
    if(fabs(val) < EPS)return 0;
    return -1;
}

struct Point
{
    double x, y;
    Point(double x=0, double y=0):x(x), y(y){}
    Point operator - (const Point &tmp) const{
        return Point(x-tmp.x, y-tmp.y);
    }
    double operator ^(const Point &tmp) const{
        return x*tmp.y - y*tmp.x;
    }
    bool operator == (const Point &tmp) const{
        return fabs(x-tmp.x) < EPS && fabs(y-tmp.y) < EPS;
    }
    double operator *(const Point &tmp) const{
        return x*tmp.x + y*tmp.y;
    }
};
struct Segment
{
    Point s, e;
    double a, b, c;///ax + by = c
    Segment(Point s=0, Point e=0):s(s), e(e){
        a = s.y - e.y;
        b = e.x - s.x;
        c = e.x*s.y - s.x*e.y;
    }
    bool Inter(const Segment &t)const{
        int v1 = sign((s-e)^(t.s-e));
        int v2 = sign((s-e)^(t.e-e));

        if(!v1 && !v2)return false;///共线

        if(!v1 && t.s.x >= min(s.x, e.x) && t.s.x <= max(s.x, e.x)
               && t.s.y >= min(s.y, e.y) && t.s.y <= max(s.y, e.y)
        || !v2 && t.e.x >= min(s.x, e.x) && t.e.x <= max(s.x, e.x)
               && t.e.y >= min(s.y, e.y) && t.e.y <= max(s.y, e.y)
        || v1 * v2 == -1)return true;

        return false;
    }
    Point CrossNode(const Segment &t) const{
        Point ans;
        ans.x = (c*t.b-t.c*b)/(a*t.b-t.a*b);
        ans.y = (c*t.a-t.c*a)/(b*t.a-t.b*a);

        return ans;
    }
};
double Dist(Point a, Point b)
{
    return sqrt((a-b) * (a-b));
}
double Find(Point crs, Point p[], int N)
{
    double sum = 0;

    for(int i=0; i<N; i++)
    for(int j=i+1; j<N; j++)
    {
        int k = sign((p[i]-crs)^(p[j]-crs));

        if(p[i] == p[j])continue;

        if(crs.x>=min(p[i].x, p[j].x) && crs.x<=max(p[i].x, p[j].x)
        || crs.x>=p[i].x && crs.x>=p[j].x && (k>0&&(p[i].x-p[j].x>EPS) || k<0&&(p[j].x-p[i].x>EPS))
        || crs.x<=p[i].x && crs.x<=p[j].x && (k<0&&(p[j].x-p[i].x>EPS) || k>0&&(p[i].x-p[j].x>EPS)))
        if(p[i].y-crs.y > EPS && p[j].y-crs.y > EPS)
        {
            Point A = p[i].y < p[j].y ? p[i] : p[j];
            Point B = (A == p[i] ? p[j] : p[i]);
            Segment t1(Point(-oo, A.y), Point(oo, A.y));
            Segment t2(crs, B);

            B = t1.CrossNode(t2);

            double La = Dist(A, B);
            double Lb = Dist(A, crs);
            double Lc = Dist(B, crs);
            double p = (La+Lb+Lc) / 2;

            sum += sqrt(p*(p-La)*(p-Lb)*(p-Lc));
        }
    }

    return sum;
}

int main()
{
    int T;

    scanf("%d", &T);

    while(T--)
    {
        Point p[MAXN], crs;

        scanf("%lf%lf%lf%lf", &p[0].x, &p[0].y, &p[1].x, &p[1].y);
        scanf("%lf%lf%lf%lf", &p[2].x, &p[2].y, &p[3].x, &p[3].y);
        Segment L1(p[0], p[1]), L2(p[2], p[3]);

        double ans = 0;

        if(L1.Inter(L2) && L2.Inter(L1))
        {
            crs = L1.CrossNode(L2);
            ans = Find(crs, p, 4);
        }

        printf("%.2f\n", ans+EPS);
    }

    return 0;
}

 

posted @ 2015-09-09 15:39  无忧望月  阅读(133)  评论(0编辑  收藏  举报
levels of contents