zoukankan      html  css  js  c++  java
  • SDOI2018 物理实验

    SDOI2018 物理实验

    题意:二维平面上有一条直线,直线上放置了一个激光发射器,会向导轨两侧沿导轨垂直方向发射宽度为 L 的激光束。平面上还有 n 条线段,并且线段和线段、线段和直线之间都没有公共点,线段和直线的夹角不超过 85◦,激光束不能穿透线段,你需要求出激光束能照射到的线段长度之和的最大值。
    做法:先进行坐标变换,将给定直线移到x轴上,注意首先将直线的一端移到原点,然后再旋转。(样例数据全都从原点出发。。。没发现。就gg了十几发,好脑残啊。。)考虑将每个线段投影到直线上,这些点将直线分成一些线段,对于每一段,找到它上方最近的那个线段,然后计算单位长度的贡献,最后的答案就可以双指针求出了。对于查询上方最近的线段,使用set维护扫描线即可。双指针还写崩了。。。这题出出来就gg了啊。。。码力弱炸,还手残。

    #include <bits/stdc++.h>
    using namespace std;
    #define rep(i,a,b) for(int i=(a);i<=(b);++i)
    #define per(i,a,b) for(int i=(a);i>=(b);--i)
    #define pb push_back
    
    typedef long double db;
    
    const db EPS = 0;
    const db INF = 1e100;
    inline int sgn(db x, db E = EPS){return x<-E?-1:x>E;}
    inline int cmp(db a,db b,db E = EPS){return sgn(a-b, E);}
    
    struct P{
    	db x,y;
    	bool operator<(P o) const { return cmp(x,o.x) != 0? cmp(x,o.x) == -1 : cmp(y,o.y) == -1; }
    	bool operator>(P o) const { return cmp(x,o.x) != 0? cmp(x,o.x) == 1 : cmp(y,o.y) == 1; }
    	bool operator==(P o) { return cmp(x,o.x) == 0 && cmp(y,o.y) == 0; }
    	void read(){ int _x,_y; scanf("%d%d",&_x,&_y); x=_x,y=_y; }
    	P operator + (P o) { return {x+o.x,y+o.y}; }
    	P operator - (P o) { return {x-o.x,y-o.y}; }
    	db det(P o) { return x*o.y-y*o.x; }
    	db dot(P o){ return x*o.x+y*o.y; }
    	db disTo(P p) { return (*this - p).abs(); }
    	db alpha() { return atan2(y, x); }
        db abs() { return sqrt(abs2());}
        db abs2() { return x * x + y * y; }
        P rot(db a) {
            db c = cos(a), s = sin(a);
            return {c*x-s*y, s*x+c*y};
        }
    };
    
    struct L {
        P ps[2];
        L(){}
        L(P p1, P p2) { ps[0] = p1, ps[1] = p2; }
        P& operator[](int i) { return ps[i]; }
        P dir() { return ps[1] - ps[0]; }
        bool include(P p) { return sgn((ps[1]-ps[0]).det(p-ps[0])); }
    };
    
    db nowx = 0;
    int top[100010];
    vector<db> scan;
    int sc;
    
    struct seg {
        P u, v; int id; db k;
        seg(){}
        seg(P _u, P _v, int _id) {
            id = _id; u = _u; v = _v;
            k = (v.y - u.y) / (v.x - u.x);
        }
        bool operator < (const seg a) const {
            db v1 = u.y + k * (nowx - u.x);
            db v2 = a.u.y + a.k * (nowx - a.u.x);
            if( cmp(v1, v2) == 0 ) return k < a.k;
            return v1 < v2;
        }
    };
    set< seg > S;
    set< seg >::iterator it[100010];
    
    struct Q {
        P e; int id;
        bool operator < (Q a) {
            if(e == a.e) return id < a.id;
            return e < a.e;
        }
    };
    vector< Q > qs;
    vector<db> cal(vector<L> ls) {
        int n = ls.size();
        qs.clear();
        rep(i,0,n-1) {
            if(ls[i][0].x > ls[i][1].x) swap(ls[i][0], ls[i][1]);
            qs.pb({ls[i][0], -i-1});
            qs.pb({ls[i][1], i+1});
        }
        sort(qs.begin(),qs.end());
        nowx = 0; S.clear();
        rep(i,0,sc-1) top[i] = -1;
        for(int j = 0, i = 0; i < sc; ++ i) {
            nowx = scan[i];
            for( ; j < qs.size() && qs[j].e.x <= nowx ; ++j) {
                if(qs[j].id < 0) {
                    int ID = (-qs[j].id)-1;
                    it[ID] = S.insert(seg(ls[ID][0],ls[ID][1],ID)).first;
                }
                else {
                    int ID = qs[j].id-1;
                    S.erase(it[ID]);
                }
            }
            if(!S.empty()) top[i] = (*S.begin()).id;
        }
        function<db(int)> cost = [&](int tp) -> db {
            return abs( ls[tp][0].disTo(ls[tp][1]) / (ls[tp][1].x - ls[tp][0].x) );
        };
        vector<db> V;
        rep(i, 0, sc-2) {
            if(top[i] != -1) V.pb(cost(top[i])); else V.pb(0);
        }
        return V;
    }
    
    db pv[100010], pc[100010];
    
    db cala(vector< pair<db,db> > &V, db Len) {
        function<db(db,int,int)> MX = [&](db LL, int p1, int p2) -> db {
            db tmp = 0;
            if(0 <= p1 && p1 <= sc-2) tmp = max(tmp, V[p1].second * min(LL, V[p1].first) );
            if(0 <= p2 && p2 <= sc-2) tmp = max(tmp, V[p2].second * min(LL, V[p2].first) );
            return tmp;
        };
        db ans = 0;
        int p1 = 0, p2 = 0; db tC = 0, tL = 0;
        do {
            if(Len >= tL) ans = max(ans, tC + MX(Len-tL, p1-1, p2 ) );
            if(p2 < sc-1 && cmp(tL + V[p2].first, Len) <= 0) {
                tL += V[p2].first;
                tC += V[p2].first * V[p2].second;
                ++ p2;
            }
            else if(p1 <= p2) {
                tL -= V[p1].first;
                tC -= V[p1].first * V[p1].second;
                ++ p1;
            }
            else {
                if(p2 < sc-1) {
                    tL += V[p2].first;
                    tC += V[p2].first * V[p2].second;
                    ++ p2;
                }
                if(p1 <= p2) {
                    tL -= V[p1].first;
                    tC -= V[p1].first * V[p1].second;
                    ++ p1;
                }
            }
            if(Len >= tL) ans = max(ans, tC + MX(Len-tL, p1-1, p2 ) );
        } while(p1 < sc-1 || p2 < sc-1);
        return ans;
    }
    
    int n;
    L line[100010];
    P p1, p2;
    db Len;
    vector<L> UP, LW;
    
    void init() {
        UP.clear(); LW.clear();
        if(p1 > p2) swap(p1, p2);
        db a = -(p2-p1).alpha();
        rep(i,0,n-1) {
            line[i][0] = (line[i][0]-p1).rot(a);
            line[i][1] = (line[i][1]-p1).rot(a);
            if( sgn(line[i][0].y) == 1 ) UP.pb(line[i]);
            else LW.pb( L( {line[i][0].x, -line[i][0].y} , {line[i][1].x, -line[i][1].y} ) );
        }
        scan.clear();
        rep(i,0,(int)UP.size()-1) { scan.pb(UP[i][0].x), scan.pb(UP[i][1].x); }
        rep(i,0,(int)LW.size()-1) { scan.pb(LW[i][0].x), scan.pb(LW[i][1].x); }
        sort(scan.begin(),scan.end()); scan.erase( unique(scan.begin(),scan.end()), scan.end());
        sc = scan.size();
    }
    
    int main() {
        int _; scanf("%d",&_);
        while(_--) {
            scanf("%d",&n);
            rep(i,0,n-1) {
                line[i][0].read();
                line[i][1].read();
            }
            p1.read(), p2.read();
            int t; scanf("%d",&t), Len = t;
    
            init();
    
            vector<db> V1 = cal(UP);
            vector<db> V2 = cal(LW);
    
            vector<pair<db,db>> V;
            rep(i, 0, (int)V1.size()-1) {
                V.pb({scan[i+1]-scan[i], V1[i] + V2[i]});
            }
            db ans = cala(V, Len);
            printf("%.12Lf
    ",ans);
        }
        return 0;
    }
    
    
  • 相关阅读:
    leetcode 414
    Leetcode 495
    Leetcode 485题
    Python 24点(2)
    python 24点
    我的第一次作业
    Django
    multiprocessing模块
    遍历文档树
    shutil模块
  • 原文地址:https://www.cnblogs.com/RRRR-wys/p/10952057.html
Copyright © 2011-2022 走看看