首先發出題目鏈接:
鏈接: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;
}