题目梗概
给出一堆点,求把这些点包起来的最小边长。
解题思路
题目描述的就是凸包所解决的问题。
因为NOIP要到了,所以复习一下凸包。
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=5005;
struct jz{
double x,y;
jz(double x=0,double y=0):x(x),y(y){}
jz operator-(const jz &b)const{return jz(x-b.x,y-b.y);}
bool operator<(const jz &b)const{
if (x==b.x) return y<b.y;
return x<b.x;
}
}a[maxn],c[maxn];
double cross(jz x,jz y){return x.x*y.y-x.y*y.x;}
double dis(jz x,jz y){return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));}
int n,len;
double ans;
void Andrew(){
sort(a+1,a+1+n);
for (int i=1;i<=n;i++){
while(len>1&&cross(c[len]-c[len-1],a[i]-c[len-1])<0) len--;
c[++len]=a[i];
}
int k=len;
for (int i=n-1;i>=1;i--){
while(len>k&&cross(c[len]-c[len-1],a[i]-c[len-1])<0) len--;
c[++len]=a[i];
}
}
int main(){
freopen("exam.in","r",stdin);
freopen("exam.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%lf%lf",&a[i].x,&a[i].y);
Andrew();
for (int i=2;i<=len;i++) ans+=dis(c[i],c[i-1]);
printf("%.2lf\n",ans);
return 0;
}