SMU Winter 2024 div2 ptlks的周报Week 4(2.19-2.25)
凸包
P2742
二维凸包的模版题,主要通过Graham算法维护凸包点集,将凸包作为上下两部分分别维护
#include <bits/stdc++.h>
using namespace std;
bool cmp(vector<double> x,vector<double> y);
bool judge(vector<double> x,vector<double> y,vector<double> z);
double distan(vector<double> x,vector<double> y);
int main(){
int n;
vector<vector<double> > a;
cin>>n;
int t[n],d[n];
for(int i=0;i<n;i++)t[i]=-1;
for(int i=0;i<n;i++){
double x,y;
cin>>x>>y;
if(i+1>a.size()){
a.resize(a.size()+1);
a[i].resize(2);
}
a[i][0]=x;
a[i][1]=y;
}
sort(a.begin(),a.end(),cmp);
//上部
t[0]=0;
t[1]=1;
int lt=2;
for(int i=2;i<a.size();i++){
for(int j=lt;j>=2&&!judge(a[t[j-2]],a[t[j-1]],a[i]);j--){
lt--;
}
t[lt]=i;
lt++;
}
//下部
d[0]=a.size()-1;
d[1]=a.size()-2;
int ld=2;
for(int i=a.size()-3;i>=0;i--){
for(int j=ld;j>=2&&!judge(a[d[j-2]],a[d[j-1]],a[i]);j--){
ld--;
}
d[ld]=i;
ld++;
}
for(int i=1;i<lt-1;i++){
d[ld]=t[i];
ld++;
}
double s=0;
for(int i=0;i<ld;i++){
if(i<ld-1){
s+=distan(a[d[i]],a[d[i+1]]);
}else {
s+=distan(a[d[i]],a[d[0]]);
}
}
printf("%.2lf",s);
return 0;
}
bool cmp(vector<double> x,vector<double> y){
if(x[0]!=y[0])return x[0]<y[0];
else return x[1]<y[1];
}
double cross(double x[],double y[]){
return x[0]*y[1]-x[1]*y[0];
}
bool judge(vector<double> x,vector<double> y,vector<double> z){
double a[2];
a[0]=x[0]-z[0];
a[1]=x[1]-z[1];
double b[2];
b[0]=y[0]-z[0];
b[1]=y[1]-z[1];
return cross(a,b)>0;
}
double distan(vector<double> x,vector<double> y){
return sqrt((x[0]-y[0])*(x[0]-y[0])+(x[1]-y[1])*(x[1]-y[1]));
}