zoukankan      html  css  js  c++  java
  • POJ 2826 (求线段交点 + 思维)

    题目:传送门

    题意:给你两条线段,问你这两条线段能接多少雨水,雨水从 y 轴正半轴往 y 轴负半轴垂直滴。

    思路:有多种情况,讨论一下即可。

    1、若有一条线段与 x 轴平行,那肯定接不了水。

    2、若两条线段不相交, 也接不了水。

    3、接口被遮住了,也不接不了水

    第三种情况的判断可以通过,判断线段的上端点向 y 轴正半轴的射线是否与 另一条线段相交,相交则接口被遮住。

    此代码C++能过,G++过不了

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <vector>
    #include <set>
    #include <string>
    #include <math.h>
    #define LL long long
    #define mem(i, j) memset(i, j, sizeof(i))
    #define rep(i, j, k) for(int i = j; i <= k; i++)
    #define dep(i, j, k) for(int i = k; i >= j; i--)
    #define pb push_back
    #define make make_pair
    #define INF 1e20
    #define inf LLONG_MAX
    #define PI acos(-1)
    using namespace std;
    
    const int N = 55;
    const double eps = 1e-8;
    
    struct Point {
        double x, y;
        Point(double x = 0, double y = 0) : x(x), y(y) { }
    };
    
    int dcmp(double x) {
        if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1;
    }
    
    Point operator + (Point A, Point B) { return Point(A.x + B.x, A.y + B.y); }
    Point operator - (Point A, Point B) { return Point(A.x - B.x, A.y - B.y); }
    Point operator * (Point A, double p) { return Point(A.x * p, A.y * p); }
    Point operator / (Point A, double p) { return Point(A.x / p, A.y / p); }
    
    double Cross(Point A, Point B) { return A.x * B.y - A.y * B.x; }
    double Dot(Point A, Point B) { return A.x * B.x + A.y * B.y; }
    
    inline Point GetLineIntersection(const Point P, const Point v, const Point Q, const Point w) {///求直线p + v*t 和 Q + w*t 的交点,需确保有交点,v和w是方向向量
        Point u = P - Q;
        double t = Cross(w, u) / Cross(v, w);
        return P + v * t;
    }
    
    inline bool Onsegment(Point p, Point a1, Point a2) { /// 判断点p是否在线段p1p2上
        return dcmp(Cross(a1 - p, a2 - p)) == 0 && dcmp(Dot(a1 - p, a2 - p)) <= 0;
    }
    
    inline bool SegmentProperInsection(Point a1, Point a2, Point b1, Point b2) { /// 判断线段是否相交
        if(dcmp(Cross(a1 - a2, b1 - b2)) == 0) /// 两线段平行
            return Onsegment(b1, a1, a2) || Onsegment(b2, a1, a2) || Onsegment(a1, b1, b2) || Onsegment(a2, b1, b2);
        Point tmp = GetLineIntersection(a1, a2 - a1, b1, b2 - b1);
        return Onsegment(tmp, a1, a2) && Onsegment(tmp, b1, b2);
    }
    
    void solve() {
        Point A, B, C, D;
        scanf("%lf %lf %lf %lf", &A.x, &A.y, &B.x, &B.y);
        scanf("%lf %lf %lf %lf", &C.x, &C.y, &D.x, &D.y);
        if(dcmp(A.y - B.y) > 0) swap(A, B);
        if(dcmp(C.y - D.y) > 0) swap(C, D);
        
        ///若有线段与 x 轴平行,则接不到水
        if(dcmp(C.y - D.y) == 0 || dcmp(A.y - B.y) == 0) { puts("0.00"); return; }
        
        /// 若两线段不相交,则接不了水
        if(SegmentProperInsection(A, B, C, D) == false) { puts("0.00"); return; }
    
        /// 若接口被遮住了也接不了水
        if(SegmentProperInsection(A, B, D, Point(D.x, 100000)) || SegmentProperInsection(C, D, B, Point(B.x, 100000))) { puts("0.00"); return; }
    
        /// 求面积
        Point tmp = GetLineIntersection(A, B - A, C, D - C);
        Point P1 = Point(100000, B.y), P2 = Point(100000, D.y);
    
        Point P = GetLineIntersection(C, D - C, B, P1 - B);
        double ans1 = fabs(Cross(B - tmp, P - tmp)) / 2.0;
    
        P = GetLineIntersection(A, B - A, D, P2 - D);
        double ans2 = fabs(Cross(D - tmp, P - tmp)) / 2.0;
    
        double ans = min(ans1, ans2);
        printf("%.2f
    ", ans);
    }
    
    int main() {
    
        int _; scanf("%d", &_);
    
        while(_--) solve();
    
        return 0;
    }
    一步一步,永不停息
  • 相关阅读:
    Python 的 Pandas 对矩阵的行进行求和
    python 统计字符串中指定字符出现次数的方法
    Python 2 代码转 Python 3的一些转化
    Python 的文件保存路径
    Pycharm 个人认为舒服漂亮又好用的主题风格
    【RS】Collaborative Memory Network for Recommendation Systems
    MATLAB 条形图添加多个图例
    MATLAB 画柱状图(/直方图)修改横坐标名称并使其横着显示
    Nexus3.X 将Maven项目上传至nexus私服
    nexus maven 使用案例
  • 原文地址:https://www.cnblogs.com/Willems/p/12383639.html
Copyright © 2011-2022 走看看