写得有点圡
水平排序版本:
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
struct point{
double x,y;
bool operator < (point &a){
return y<a.y || (y == a.y && x<a.x);
}
};
bool mult(point &sp,point &ep,point &op){
return (sp.x-op.x)*(ep.y-op.y)
>=(ep.x-op.x)*(sp.y-op.y);
}
double dist(point &a,point &b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double graham(point *pnt,int n,point res[]){
int i,len,k=0,top=1;
sort(pnt,pnt+n);
if(n==0) return 0; res[0]=pnt[0];
if(n==1) return 0; res[1]=pnt[1];
if(n==2) return dist(pnt[0],pnt[1]); res[2]=pnt[2];
for(i=2;i<n;i++){
while(top && mult(pnt[i],res[top],res[top-1])) //左转退栈,上凸包
top--;
res[++top]=pnt[i];
}
len=top;
res[++top]=pnt[n-2];
for(i=n-3;i>=0;i--){
while(top!=len && mult(pnt[i],res[top],res[top-1]))//下凸包。
top--;
res[++top]=pnt[i];
}
double area=0;
for(i=1;i<=top;i++){
area+=dist(res[i],res[(i+1)>top?1:(i+1)]);
}
return area;
}
int main(){
int n;
point pnt[105],res[105];
while(scanf("%d",&n) && n){
for(int i=0;i<n;i++)
scanf("%lf %lf",&pnt[i].x,&pnt[i].y);
printf("%.2lf\n",graham(pnt,n,res));
}
return 0;
}
极角排序版本:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
typedef struct point{
double x,y;
bool operator < (point &a){
return y<a.y || (y==a.y && x<a.y); //重载小于号
}
}p;
p temp;
double dist(p &a,p &b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp(p &a,p &b){
double xmt=(a.x-temp.x)*(b.y-temp.y)-(b.x-temp.x)*(a.y-temp.y);
if(xmt) //向量不共线就按逆时针旋转
return xmt>0;
return dist(a,temp)>dist(b,temp);//向量共线取最长的。
}
bool xmult(p& a,p& b,p& t){ //叉乘大于0 往左转,叉乘小于0往右转,等于0向量共线
return (a.x-t.x)*(b.y-t.y)>=(b.x-t.x)*(a.y-t.y);
}
void swap(p& a,p &b){
temp=b;
b=a;
a=temp;
}
double graham(p *pnt,int n,p *res){ //Graham扫描法
if(n==1) return 0;
if(n==2) return dist(pnt[0],pnt[1]);
int top=-1;
for(int i=0;i<n;i++){
while(top>1 && xmult(pnt[i],res[top],res[top-1]))
top--;
res[++top] = pnt[i];
}
double dis=0;
for(int j=0;j<=top;j++){
dis+=dist(res[j],res[(j+1)%(top+1)]);
}
return dis;
}
int main(){
int n;
p pnt[105],res[105];
while(scanf("%d",&n) && n){
int t;
for(int i=0;i<n;i++){
scanf("%lf %lf",&pnt[i].x,&pnt[i].y);
if(!i || pnt[i]<pnt[t]) //找出最小y坐标值并且最靠左的点
t=i;
}
swap(pnt[0],pnt[t]);
sort(pnt+1,pnt+n,cmp);
printf("%.2lf\n",graham(pnt,n,res));
}
return 0;
}