计算几何题集

ACM训练 专栏收录该内容
26 篇文章 0 订阅

判断点和射线的那边

向量叉乘判断符号解决。向量叉乘使用右手法则。
v 1 = ( x 1 , y 1 ) , v 2 = ( x 2 , y 2 ) v 1 × v 2 = x 1 ∗ y 2 − y 1 ∗ x 2 v_1=(x1,y1),v2=(x2,y2) \\ v1×v2=x1*y2-y1*x2 v1=(x1,y1),v2=(x2,y2)v1×v2=x1y2y1x2
在这里插入图片描述
例:
HDU 6857 依次给出三个点,求是顺时针旋转还是逆时针。
s = v 13 × v 23 = ( x 1 − x 3 ) ( y 2 − y 3 ) − ( y 1 − y 3 ) ( x 2 − x 3 ) s=v_{13}×v_{23}= (x1-x3)(y2-y3)-(y1-y3)(x2-x3) s=v13×v23=(x1x3)(y2y3)(y1y3)(x2x3)
则结合右手法则可知,
{ s < 0 , 顺 时 针 s > 0 , 逆 时 针 \{\begin{aligned}s<0, 顺时针\\ s>0, 逆时针\end{aligned} {s<0,s>0,

POJ 3304
判断n个线段能否投影到一条直线上至少有一个共同点。容易转化为问题:n个线段是否能被一条直线(与投影轴垂直)穿过。枚举所有点两两成的直线能否串过所有线段。用跨立实验判断直线和线段是否相交。

#include<iostream>
#include<vector>
#include<algorithm>
#include<map>
#include<utility>
#include<cmath>
#include<stack>
#include<set>
#include<cstring>
#include<string>
using namespace std;
// #define endl '\n'
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=1e5+3;
const ll mod =  1e9+7;
struct Point{
    double x,y;
    Point operator- (const Point &v) const {
        return Point{x-v.x, y-v.y};
    }
    int operator* (const Point &v) const {
        double flag = x*v.y - y*v.x;
        if(abs(flag)<1e-8)return 0;
        return flag>0 ? 1 : -1;
    }
    double len(){
        return sqrt(x*x+y*y);
    }
};
struct Line{
    Point p1, p2;
    int judge_point(Point v){
        Point pa = p1 - p2;
        Point pb = p1 - v;
        return pa * pb;
    }
};
Point p[305];
Line seg[305];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    int tt;
    cin>>tt;
    while(tt--){
        int n;
        cin>>n;
        for(int i=0;i<2*n;++i){
            cin>>p[i].x>>p[i].y;
        }
        for(int i=0;i<n;++i){
            seg[i] = Line{p[2*i],p[2*i+1]};
        }
        int flag = false;
        for(int i=0;i<2*n && !flag;++i){
            for(int j=i+1;j<2*n && !flag;++j){
                if((p[i]-p[j]).len()<1e-8)continue; // key!!! 两个点相同就不能成直线
                Line lne = Line{p[i],p[j]};
                bool f=true;
                for(int k=0;k<n;++k){
                    int f1 = lne.judge_point(seg[k].p1);
                    int f2 = lne.judge_point(seg[k].p2);
                    if(!f1 || !f2 || f1!=f2)continue;
                    f=false;
                    break;
                }
                if(f)flag = true;
            }
        }
        if(flag)cout<<"Yes!"<<endl;
        else cout<<"No!"<<endl;
    }
}

Intersecting Lines
求两直线交点

x0 = ((x3-x4) * (x2*y1 - x1*y2) - (x1-x2) * (x4*y3 - x3*y4)) / ((x3-x4) * (y1-y2) - (x1-x2) * (y3-y4));
y0 = ((y3-y4) * (y2*x1 - y1*x2) - (y1-y2) * (y4*x3 - y3*x4)) / ((y3-y4) * (x1-x2) - (y1-y2) * (x3-x4));
#include<iostream>
#include<vector>
#include<algorithm>
#include <iomanip>
#include<map>
#include<utility>
#include<cmath>
#include<stack>
#include<set>
#include<cstring>
#include<string>
using namespace std;
// #define endl '\n'
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=1e5+3;
const ll mod =  1e9+7;
struct Point{
    double x,y;
    Point operator- (const Point &v) const {
        return Point{x-v.x, y-v.y};
    }
    int operator* (const Point &v) const {
        double flag = x*v.y - y*v.x;
        if(abs(flag)<1e-8)return 0;
        return flag>0 ? 1 : -1;
    }
    double len(){
        return sqrt(x*x+y*y);
    }
};
struct Line{
    Point p1, p2;
    int judge_point(Point v){
        Point pa = p1 - p2;
        Point pb = p1 - v;
        return pa * pb;
    }
};
Point p[305];
Line seg[305];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    int tt;
    cin>>tt;
    cout<<"INTERSECTING LINES OUTPUT"<<endl;
    while(tt--){
        Line la, lb;
        cin>>la.p1.x>>la.p1.y>>la.p2.x>>la.p2.y>>lb.p1.x>>lb.p1.y>>lb.p2.x>>lb.p2.y;
        Point va = la.p1 - la.p2;
        Point vb = lb.p1 - lb.p2;
        int flag = va * vb;
        if(!flag){
            if(!la.judge_point(lb.p1))cout<<"LINE"<<endl;
            else cout<<"NONE"<<endl;
            continue;
        }
        double x1 =  la.p1.x;
        double y1 = la.p1.y;
        double x2 =  la.p2.x;
        double y2 = la.p2.y;
        double x3 =  lb.p1.x;
        double y3 = lb.p1.y;
        double x4 =  lb.p2.x;
        double y4 = lb.p2.y;
        double x0 = ((x3-x4) * (x2*y1 - x1*y2) - (x1-x2) * (x4*y3 - x3*y4)) / ((x3-x4) * (y1-y2) - (x1-x2) * (y3-y4));
        double y0 = ((y3-y4) * (y2*x1 - y1*x2) - (y1-y2) * (y4*x3 - y3*x4)) / ((y3-y4) * (x1-x2) - (y1-y2) * (x3-x4));
        cout<<"POINT "<<fixed<<setprecision(2)<<x0<<" "<<y0<<endl;
    }
    cout<<"END OF OUTPUT"<<endl;
}

POJ - 1556
在这里插入图片描述
每个点两两看有没有穿过墙,没穿过则建边,跑最短路。
没有做快速排斥实验,因为不可能有边与墙共线的情况。

#include<iostream>
#include<vector>
#include<algorithm>
#include<map>
#include<utility>
#include<cmath>
#include<stack>
#include<set>
#include<cstring>
#include<string>
#include<iomanip>
#include<queue>
// #define endl '\n'
using namespace std;
#define debug(_x) cout<<#_x<<": "<<_x<<endl;
typedef long long ll;
const int maxn = 1e5+4;
struct Point{
    double x,y;
    double operator^ (const Point &v) const {
        double res = x * v.y - v.x * y;
        if(abs(res) < 1e-6) return 0;
        return res;
    }
    Point operator- (const Point &v) const {
        return Point{x-v.x, y-v.y};
    }
    double len(){
        return sqrt(x*x+y*y);
    }
};
struct Line{
    Point p1,p2;
    Point dir(){
        return p1 - p2;
    }
};
bool is_cross(Line l1, Line l2){
    Point d1 = l1.dir(), d2 = l2.dir();
    return ((l1.p1 - l2.p1) ^ d1) * (d1 ^ (l1.p1 - l2.p2)) > 0 && ((l2.p1 - l1.p1) ^ d2) * (d2 ^ (l2.p1 - l1.p2)) > 0;
}
struct Edge{
    int to;
    double dis;
    bool operator< (const Edge& v){
        return dis>v.dis;
    }
};
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    int n;
    while(cin>>n && ~n){
        vector<Point> p;
        vector<Line> e;
        p.push_back(Point{0,5});
        for(int k=0;k<n;++k){
            double tx,y[4];
            cin>>tx;
            for(int i=0;i<4;++i){
                cin>>y[i];
                p.push_back(Point{tx,y[i]});
            }
            e.push_back(Line{Point{tx,0},Point{tx,y[0]}});
            e.push_back(Line{Point{tx,y[1]},Point{tx,y[2]}});
            e.push_back(Line{Point{tx,y[3]},Point{tx,10}});
        }
        p.push_back(Point{10,5});
        vector<vector<Edge> > G(p.size());
        vector<bool> in(p.size());
        vector<double> d(p.size(), 1e8);
        for(int i=0;i<p.size();++i){
            for(int j=i+1;j<p.size();++j){
                if(p[i].x == p[j].x)continue;
                int flag = 1;
                Line lp = Line{p[i],p[j]};
                for(int k=0;k<e.size();++k){
                    if(is_cross(e[k],lp)){
                        flag = 0;
                        break;
                    }
                }
                if(flag){
                    G[i].push_back(Edge{j, (p[j]-p[i]).len()});
                }
            }
        }
        queue<Edge> Q;
        d[0] = 0;
        Q.push(Edge{0,0});
        while(!Q.empty()){
            Edge u = Q.front();
            in[u.to] = 0;
            Q.pop();
            for(int i=0;i<G[u.to].size();++i){
                Edge v = G[u.to][i];
                if(d[v.to]>d[u.to]+v.dis){
                    d[v.to] = d[u.to] + v.dis;
                    if(in[v.to])continue;
                    in[v.to] = 1;
                    v.dis = d[v.to];
                    Q.push(v);
                }
            }
        }
        cout<<fixed<<setprecision(2)<<d[p.size()-1]<<endl;
    }
}

POJ - 2653
木棒压木棒,求没被压的木棒。
在这里插入图片描述

#include<iostream>
#include<vector>
#include<algorithm>
#include <iomanip>
#include<map>
#include<utility>
#include<cmath>
#include<stack>
#include<set>
#include<cstring>
#include<string>
#include<list>
#include<cstdio>
using namespace std;
// #define endl '\n'
typedef long long ll;
typedef pair<int,int> pii;
struct Point{
    double x, y;
    double operator* (const Point &p) const {
        return x*p.y - p.x*y;
    }
    Point operator- (const Point &p) const {
        return Point{x-p.x, y-p.y};
    }
    double len(){
        return sqrt(x*x+y*y);
    }

};
struct Line{
    Point a,b;
    Point dir() const{
        return a - b;
    }
    double judge_point(const Point &p) const{
        return this->dir() * (a - p);
    }
};
bool iscross(Line s1,Line s2){
    return min(s1.a.x,s1.b.x) < max(s2.a.x,s2.b.x)
        && min(s1.a.y,s1.b.y) < max(s2.a.y,s2.b.y)
        && min(s2.a.x,s2.b.x) < max(s1.a.x,s1.b.x)
        && min(s2.a.y,s2.b.y) < max(s1.a.y,s1.b.y)
        && s1.judge_point(s2.a) * s1.judge_point(s2.b) <= 0
        && s2.judge_point(s1.a) * s2.judge_point(s1.b) <= 0;
}
int main(){
    int n;
    while(~scanf("%d", &n) && n){
        list<pair<Line,int> > lines;
        Line tl;
        for(int i = 0;i < n;++i){
            scanf("%lf%lf%lf%lf",&tl.a.x,&tl.a.y,&tl.b.x,&tl.b.y);
            for(list<pair<Line,int> >::iterator it = lines.begin();it!=lines.end();){
                if(iscross(it->first, tl))it = lines.erase(it);
                else ++it;
            }
            lines.push_back(make_pair(tl, i+1));
        }
        printf("Top sticks: %d", lines.begin()->second);
        for(list<pair<Line,int> >::iterator it = lines.begin();it!=lines.end();++it){
            if(it == lines.begin())continue;
            printf(", %d", it->second);
        }
        printf(".\n");
    }
}

POJ - 1066
在这里插入图片描述
每次从线段的中点穿过,问穿过多少面墙能到达宝藏位置。由于每条直线穿过整个正方形。转弯无法减少穿过数。所以枚举每个中点作射线就行。而枚举每个顶点也一样。

#include<iostream>
#include<vector>
#include<algorithm>
#include <iomanip>
#include<map>
#include<utility>
#include<cmath>
#include<stack>
#include<set>
#include<cstring>
#include<string>
#include<list>
#include<cstdio>
using namespace std;
// #define endl '\n'
typedef long long ll;
typedef pair<int,int> pii;
struct Point{
    double x, y;
    double operator* (const Point &p) const {
        return x*p.y - p.x*y;
    }
    Point operator- (const Point &p) const {
        return Point{x-p.x, y-p.y};
    }
    double len(){
        return sqrt(x*x+y*y);
    }
    bool operator==  (const Point &p) const {
        return x==p.x && y==p.y;
    }

};
struct Line{
    Point a,b;
    Point dir() const{
        return a - b;
    }
    double judge_point(const Point &p) const{
        return this->dir() * (a - p);
    }
};
bool iscross(Line s1,Line s2){
    return min(s1.a.x,s1.b.x) <= max(s2.a.x,s2.b.x)
        && min(s1.a.y,s1.b.y) <= max(s2.a.y,s2.b.y)
        && min(s2.a.x,s2.b.x) <= max(s1.a.x,s1.b.x)
        && min(s2.a.y,s2.b.y) <= max(s1.a.y,s1.b.y)
        && s1.judge_point(s2.a) * s1.judge_point(s2.b) < 1e-8
        && s2.judge_point(s1.a) * s2.judge_point(s1.b) < 1e-8;
}
int main(){
    int n;
    while(~scanf("%d", &n)){
        vector<Line> lines;
        vector<Point> p;
        Line tl;
        for(int i = 0;i < n;++i){
            scanf("%lf%lf%lf%lf",&tl.a.x,&tl.a.y,&tl.b.x,&tl.b.y);
            lines.push_back(tl);
            p.push_back(tl.a);
            p.push_back(tl.b);
        }
        int ans = 1e9;
        scanf("%lf%lf",&tl.b.x,&tl.b.y);
        for(int k=0;k<p.size();++k){
            int no=0;
            tl.a = p[k];
            for(int i=0;i<lines.size();++i){
                no+=iscross(tl, lines[i]);
            }
            ans = min(ans,no);
        }
        if(ans > 2*n)ans = 1;
        printf("Number of doors = %d\n", ans);
    }
}

POJ - 1696
在这里插入图片描述
从Plant A出发,只能往左转最多能走多少个点,依次输出。只要每次选当前点为基准,极角排序,选极角最小的,必能走完所有的点。

#include<iostream>
#include<vector>
#include<algorithm>
#include <iomanip>
#include<map>
#include<utility>
#include<cmath>
#include<stack>
#include<set>
#include<cstring>
#include<string>
#include<list>
#include<cstdio>
#define endl '\n'
using namespace std;
struct Point{
    int idx;
    int x, y;
    int operator^ (const Point &p) const{
        return x*p.y - y*p.x;
    }
    Point operator- (const Point &p) const{
        return Point{0, x-p.x, y-p.y};
    }
    double len(){
        return sqrt(x*x+y*y);
    }
};
int sgn(const int x){
    if(abs(x)<1e-8)return 0;
    return x < 0 ? -1 : 1;
}
Point mark;
bool cmp(const Point &a, const Point &b){
    Point da = a - mark;
    Point db = b - mark;
    switch(sgn(da ^ db)){
    case 1:
        return 1;
    case -1:
        return 0;
    default:
        return da.len() < db.len();
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    int tt;
    cin>>tt;
    while(tt--){
        int n;
        cin>>n;
        vector<Point> v(n);
        for(int i=0;i<n;++i){
            cin>>v[i].idx>>v[i].x>>v[i].y;
            if(!i)mark = v[i];
            else if(v[i].y < mark.y)mark = v[i];
        }
        swap(v[mark.idx-1],v[0]);
        for(int i=1;i<n;++i){
            mark = v[i-1];
            sort(v.begin()+i,v.end(),cmp);
        }
        cout<<n;
        for(int q = 0; q < n; ++q){
            cout<<' '<<v[q].idx;
        }
        cout<<endl;
    }
}

Dancing Stars on Me
给出N个乱序的点,问这些点能不能组成正N边形。
思路:先找到y坐标最小的那个点,作为第一个点,将后面N-1个点依次以上一个点为KEY点做极角排序。判断每条边长度是否相同,相邻边的角度是否相同(可用内积,外积)。

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
const int inf = 2e9;
const double eps = 1e-6;
using ll = long long;
struct Point{
    int x, y;
    double len(){
        return sqrt(1ll*x*x+1ll*y*y);
    }
    Point operator- (const Point& ot) const{
        return Point{x-ot.x, y-ot.y};
    }
    ll operator* (const Point& ot) const{
        return x*ot.y - y*ot.x;
    }
}key;
int sgn(double x){
    if(x==0)return 0;
    return x < 0 ? -1 : 1;
}
bool cmp(const Point& a, const Point& b){
    Point va = a - key, vb = b - key;
    switch(sgn(va * vb)){
    case 0:
        return va.len() < vb.len();
    case 1:
        return 1;
    case -1:
        return 0;
    }
}
int main(){
    int tt;
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    cin >> tt;
    while(tt--){
        int n;
        cin >> n;
        vector<Point> v;
        int idx = 0;
        for(int i=0;i<n;++i){
            Point x;
            cin >> x.x >> x.y;
            v.push_back(x);
            if(x.y < v[0].y || x.y==v[0].y && x.x < v[0].x)
                swap(v[i], v[0]);
        }
        for(int i=0;i+1<n;++i){
            key = v[i];
            sort(v.begin()+i+1, v.end(), cmp);
        }
        v.push_back(v[0]);
        v.push_back(v[1]);
        int flag = 1;
        ll inj = -1;
        for(int i=0;i<n;++i){
            // cout << v[i].x << "," << v[i].y << endl;
            Point a = v[i+1] - v[i], b = v[i+2] - v[i+1];
            if(i==0)inj = a * b;
            if(a.len()!=b.len() || a*b != inj){
                flag = 0;
                break;
            }
        }
        cout << (flag ? "YES" : "NO") << endl;
    }
}

Surround the Trees
求二维凸包的周长。

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
const int inf = 2e9;
const double eps = 1e-6;
using ll = long long;
using pdd = pair<double, double>;
const double PI = acos(-1);
const int maxn = 2e5+5;
int sgn(double x){
    if(x==0)return 0;
    return x < 0 ? -1 : 1;
}
struct Point{
    int x, y;
    double len(){
        return sqrt(1ll*x*x+1ll*y*y);
    }
    Point operator- (const Point& ot) const{
        return Point{x-ot.x, y-ot.y};
    }
    ll operator* (const Point& ot) const{
        return x*ot.y - y*ot.x;
    }
}key, sta[maxn];
bool cmp(const Point& a, const Point& b){
    Point va = a - key, vb = b - key;
    switch(sgn(va * vb)){
    case 0:
        return va.len() < vb.len();
    case 1:
        return 1;
    case -1:
        return 0;
    }
}
int main(){
    int tt;
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int n;
    while(cin >> n && n){
        vector<Point> v(n);
        for(Point& p : v){
            cin >> p.x >> p.y;
        }

        if(n==1){
            cout << 0 << endl;
            continue;
        }else if(n==2){
            cout << fixed << setprecision(2) << (v[1] - v[0]).len() << endl;
            continue;
        }


        int id = 0;
        for(int i=1;i<n;++i){ // 选出最下,最左的点
            if(v[i].y < v[id].y || v[i].y == v[id].y && v[i].x < v[id].x)id = i;
        }
        swap(v[0], v[id]);
        key = v[0];
        sort(v.begin()+1, v.end(), cmp); // 极角排序
        int top = 0;
        sta[0] = v[0];
        for(int i=1;i<n;++i){
            while(top > 0 && sgn( (sta[top] - sta[top-1]) * (v[i] - sta[top]) ) < 0)
                top--; // 踢掉右转的
            sta[++top] = v[i];
        }
        double sum = 0;
        sta[++top] = v[0];
        for(int i=0;i<top;++i){
            sum += (sta[i+1] - sta[i]).len();
        }
        cout << fixed << setprecision(2) << sum << endl;
    }
}

旋转卡壳

[HNOI2007]最小矩形覆盖
题意:二维平面给一堆点,求最小的矩形包括所有的点。输出矩形面积和4个坐标。
思路:旋转卡壳模板。维护三个卡壳点,因为三者都是单峰函数,所以可以实现。

  • p是离当前枚举边 ( i , i + 1 ) (i, i + 1) (i,i+1)最远的点,用叉乘求三角形面积来判断,通过p就求出了矩形的高H
  • fr是所有点投影到当前枚举边 ( i , i + 1 ) (i, i + 1) (i,i+1),设 i i i i + 1 i+1 i+1为正方向,最负的点
  • ba是最正的点,fr、ba使用点乘求投影来判断
#include<bits/stdc++.h>
// #define endl '\n'
#define IOS ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
using namespace std;
const int N = 5e4 +5;
const double eps = 1e-10;
struct Coor{
    double x, y;
    double operator^ (const Coor & ot) const &{
        return x * ot.y - y * ot.x;
    }
    double operator* (const Coor & ot) const &{
        return x * ot.x + y * ot.y;
    }
    double len(){
        return sqrt(x * x + y * y);
    }
    Coor operator- (const Coor & ot) const &{
        return Coor{x - ot.x, y - ot.y};
    }
    Coor operator+ (const Coor & ot) const &{
        return Coor{x + ot.x, y + ot.y};
    }
}a[N], sta[N], key, rect[4];
Coor operator* (const double & c, const Coor & v){
    return Coor{v.x * c, v.y * c};
}
int sgn(double v){
    if(abs(v) < eps)return 0;
    return v < 0 ? -1 : 1;
}
bool cmp(const Coor &a, const Coor &b){
    Coor da = a - key, db = b - key;
    switch(sgn(da ^ db)){
    case 1:
        return true;
    case -1:
        return false;
    default:
        return da.len() < db.len();
    }
}
double area(int i, int j, int k){
    return (sta[j] - sta[i]) ^ (sta[k] - sta[i]);
}
double project(int i, int j, int k){
    return (sta[j] - sta[i]) * (sta[k] - sta[i]);
}
int main(){
    IOS;
    int n;
    cin >> n;
    int id = 0;
    for(int i = 0; i < n; ++i){
        cin >> a[i].x >> a[i].y;
        if(a[i].y < a[id].y || a[i].y == a[id].y && a[i].x < a[id].x)id = i;
    }
    swap(a[id], a[0]);
    key = a[0];
    sort(a+1, a+n, cmp);
    int top = 0;
    sta[0] = a[0];
#define U(_ar, _i) cout << "(" << _ar[_i].x << "," << _ar[_i].y << ") ";
    for(int i = 1; i < n; ++i){
        while(top > 0 && sgn((sta[top] - sta[top - 1]) ^ (a[i] - sta[top])) <= 0)top--;
        sta[++top] = a[i];
    }
    sta[++top] = sta[0];
    int p = 1, ba = 1, fr = 1;
    double ans = 2e14;
    for(int i = 0; i < top; ++i){
        while(sgn(area(i, i + 1, p) - area(i, i + 1, p + 1)) <= 0)
            p = (p + 1) % top;
        while(sgn(project(i, i + 1, fr)) > 0 || sgn(project(i, i + 1, fr) - project(i, i + 1, (fr + 1) % top)) >= 0)
            fr = (fr + 1) % top;
        while(sgn(project(i, i + 1, ba) - project(i, i + 1, (ba + 1) % top)) < 0)
            ba = (ba + 1) % top;
        double L = (sta[i + 1] - sta[i]).len(), H = area(i, i + 1, p), C = (sta[i + 1] - sta[i]) * (sta[ba] - sta[fr]);
//        assert(sgn(C) > 0);
//        assert(sgn(H) > 0);
        if(sgn(H * C - ans * L * L) < 0){
            ans = H * C / (L * L);
            H /= L;
            Coor I = 1 / L * (sta[i + 1] - sta[i]); // 单位向量
            double pf = (sta[fr] - sta[i]) * I; // f投影大小
            double pb = (sta[ba] - sta[i]) * I; // b投影大小
            rect[0] = sta[i] + pf * I;
            rect[1] = sta[i] + pb * I;
            Coor Vert = sgn(I.y) == 0 ? Coor{0, 1} : Coor{1, -I.x / I.y};
            if(sgn(I ^ Vert) < 0)Vert = -1 * Vert;
            Vert = H / Vert.len() * Vert;
            rect[2] = rect[1] + Vert;
            rect[3] = rect[0] + Vert;
//            cout << ans << endl;
//            for(int fi = 0, i = 0; i < 4; ++i){
//                cout << rect[fi].x << " " << rect[fi].y << endl;
//                fi = (fi + 1) % 4;
//            }
        }
    }
    if(sgn(ans) == 0) ans = 0;
    cout << fixed << setprecision(5) << ans + 1e-8 << endl;
    int fi = 0;
    for(int i = 1; i < 4; ++i){
        if(sgn(rect[i].y - rect[fi].y) < 0 || sgn(rect[i].y - rect[fi].y) == 0 && sgn(rect[i].x - rect[fi].x) < 0)
            fi = i;
    }
    for(int i = 0; i < 4; ++i){
        if(sgn(rect[fi].x) == 0)rect[fi].x = 0;
        if(sgn(rect[fi].y) == 0)rect[fi].y = 0;
        cout << rect[fi].x << " " << rect[fi].y << endl;
        fi = (fi + 1) % 4;
    }
}
  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值