2019牛客暑期多校訓練營(第二場)----G-Polygons

首先發出題目鏈接:
鏈接:https://ac.nowcoder.com/acm/contest/882/G
來源:牛客網
涉及:計算幾何

點擊這裏回到2019牛客暑期多校訓練營解題—目錄貼


題目如下:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
代碼如下:

#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <functional>
using namespace std;
const int maxn=1005;
const int maxm=10005;
const double EP=1.0e-8;
struct Point{
    double x,y;
    bool exist;
    Point(double _x=0,double _y=0,bool _exist=true){
        this->x=_x,this->y=_y,this->exist=_exist;
    }
    Point operator-(const Point &a)const{
        return Point(this->x-a.x,this->y-a.y);
    }
    double operator^(const Point &a)const{
        return this->x*a.y-a.x*this->y;
    }
};
struct Line{
    Point begin,end;
    Line(Point _begin=Point(0,0,false),Point _end=Point(0,0,false)){
        this->begin=_begin,this->end=_end;
    }
};
struct Edge{
    int to;
    bool exist;
    Edge(int _to=-1,bool _exist=true){
        this->to=_to,this->exist=_exist;
    }
};
vector<Point> points;
vector<Line> lines;
vector<int> seg[maxn];
vector<Edge> edge[maxn*maxn];
vector<int> border;
vector<double> ans;
int n,m;
int check(double x){
    if(fabs(x)<EP)   return 0;
    if(x<0)  return -1;
    return 1;
}
bool checkParallel(Line l1,Line l2){
    return fabs((l1.end-l1.begin)^(l2.end-l2.begin))<EP;
}
Point getIntersection(Line l1,Line l2){
    if(checkParallel(l1,l2))    return Point(0,0,false);
    Point p=l1.begin;
    double inv=(l2.end-l2.begin)^(l1.begin-l2.begin);
    inv/=(l1.end-l1.begin)^(l2.end-l2.begin);
    p.x+=inv*(l1.end.x-l1.begin.x);
    p.y+=inv*(l1.end.y-l1.begin.y);
    return p;
}
bool comp(int a,int b){
    if(check(points[a].x-points[b].x)!=0)    return points[a].x<points[b].x;
    return points[a].y<points[b].y;
}
bool dfs(int last,int now){
    border.push_back(now);
    if(now==border[0]){
        double area=0.0;
        for(int i=0;i<border.size()-1;i++)   area+=(points[border[i]])^(points[border[i+1]]);
        ans.push_back(fabs(area/2.0));
        return true;
    }
    int next=-1;
    for(int i=0;i<edge[now].size();i++){
        int pos=edge[now][i].to;
        if(pos==last || !edge[now][i].exist)    continue;
        if(check((points[pos]-points[now])^(points[now]-points[last]))<0 && (next==-1 || check((points[pos]-points[now])^(points[edge[now][next].to]-points[now]))<0)){
            next=i;
        }
    }
    if(next==-1)    return false;
    if(dfs(now,edge[now][next].to)){
        edge[now][next].exist=false;
        return true;
    }
    else    return false;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        double x1,y1,x2,y2;
        scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
        lines.push_back(Line(Point(x1,y1),Point(x2,y2)));
    }
    for(int i=0;i<n-1;i++){
        for(int j=i+1;j<n;j++){
            Point inter=getIntersection(lines[i],lines[j]);
            if(!inter.exist)    continue;
            points.push_back(inter);
            seg[i].push_back(points.size()-1);
            seg[j].push_back(points.size()-1); 
        }
    } 
    for(int i=0;i<=n;i++){
        sort(seg[i].begin(),seg[i].end(),comp);
        for(int j=1;j<seg[i].size();j++){
            edge[seg[i][j]].push_back(Edge(seg[i][j-1]));
            edge[seg[i][j-1]].push_back(Edge(seg[i][j]));
        }
    }  
    for(int i=0;i<points.size();i++){
        for(int j=0;j<edge[i].size();j++){
            border.clear();
            border.push_back(i);
            if(edge[i][j].exist && dfs(i,edge[i][j].to)){
                edge[i][j].exist=false;
            }
        }
    }
    sort(ans.begin(),ans.end(),greater<double>{});
    printf("%d %.6lf %.6lf\n",ans.size(),ans[0],ans[ans.size()-1]);
    scanf("%d",&m);
    while(m--){
        int place;
        scanf("%d",&place);
        if(place>=0 && place<=ans.size()) printf("%.6lf\n",ans[place-1]);
        else    printf("Invalid question\n");
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章