一开始用两边扫的过不去,后来自己加了初始化就过了,郁闷一晚上。。。
凸包求周长。。。
两边扫点
#include<iostream>
#include<algorithm>
#include<cmath>
#define MAX 2000
#define eps 1e-9
using namespace std;
struct points
{
double x,y;
};
points p[MAX];
int n,l,res[MAX],top;
double mult(points sp,points ep,points op)
{
return (sp.x-op.x)*(ep.y-op.y)>=(ep.x-op.x)*(sp.y-op.y);
}
bool cmp(const points &a,const points &b)
{
if(a.y-b.y==eps)return a.x-b.x<eps;
return a.y-b.y<eps;
}
void graham()
{
int i,len;
top=1;
sort(p,p+n,cmp);
if(n==0)return; res[0]=0;
if(n==1)return; res[1]=1;
if(n==2)return; res[2]=2;
for(i=2;i<n;i++)
{
while(top && mult(p[i],p[res[top]],p[res[top-1]]))
top--;
res[++top]=i;
}
len=top;
res[++top]=n-2;
for(i=n-3;i>=0;i--)
{
while(top!=len && mult(p[i],p[res[top]],p[res[top-1]]))
top--;
res[++top]=i;
}
}
double dists(points aa,points bb)
{
return sqrt((aa.x-bb.x)*(aa.x-bb.x)+(aa.y-bb.y)*(aa.y-bb.y));
}
int main()
{
while(scanf("%d",&n)!=EOF && n)
{
memset(p,0,sizeof(p));
memset(res,0,sizeof(res));
{
for(int i=0;i<n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
if(n<2)printf("0.00\n");
else
if(n==2)printf("%.2lf\n",dists(p[0],p[1]));
else
{
graham();
double re=0;
/* for(int i=0;i<top;i++)
{
cout<<"..."<<p[res[i]].x<<" "<<p[res[i]].y<<endl;
}*/
for(int i=0;i<top;i++)
re+=dists(p[res[i]],p[res[(i+1)%(top+1)]]);
printf("%.2lf\n",re);
}
}
}
return 0;
}
用tan来排序那么扫点只用1次,因为tan是单调的
#include<iostream>
#include<algorithm>
#include<cmath>
#define MAX 1000
#define eps 1e-12
using namespace std;
struct points
{
double x,y;
double atan;
};
points p[MAX],res[MAX];
int n,l,top;
double mult(points sp,points ep,points op)
{
return (sp.x-op.x)*(ep.y-op.y)>=(ep.x-op.x)*(sp.y-op.y);
}
bool ral(points p1,points p2,points p3)
{
return (p3.x-p1.x)*(p2.y-p1.y)>=(p2.x-p1.x)*(p3.y-p1.y);
}
bool cmp(const points &a,const points &b)
{
if(a.y-b.y==eps||a.y-b.y==0)return a.x-b.x<eps;
return a.y-b.y<eps;
/* return a.y<b.y||(a.y==b.y&&a.x<b.x);*/
}
int cmp2(points a,points b)
{
return a.atan<b.atan || ( a.atan==b.atan && a.x<b.x );
}
void graham()
{
int i,len;
top=1;
sort(p,p+n,cmp);
/**/
p[0].atan=0;
for (int i=1;i<n;i++)
p[i].atan=atan2(p[i].y-p[0].y,p[i].x-p[0].x);
sort(p,p+n,cmp2);
/**/
/*
if(n==0)return; res[0]=0;
if(n==1)return; res[1]=1;
if(n==2)return; res[2]=2;*/
res[0]=p[0];
res[1]=p[1];
for(i=2;i<n;i++)
{
while(top && ral(res[top-1],res[top],p[i]))
top--;
res[++top]=p[i];
}
/*if(top>2 && ral(res[top-1],res[top],p[i]))
top--;
len=top;
res[++top]=n-2;
for(i=n-3;i>=0;i--)
{
while(top != len && mult(p[i],p[res[top]],p[res[top-1]]))
top--;
res[++top]=i;
}*/
}
double dists(points aa,points bb)
{
return sqrt((aa.x-bb.x)*(aa.x-bb.x)+(aa.y-bb.y)*(aa.y-bb.y));
}
int main()
{
while(scanf("%d",&n)!=EOF && n)
{
for(int i=0;i<n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
if(n<2)printf("0.00\n");
else
if(n==2)printf("%.2lf\n",dists(p[0],p[1]));
else
{
graham();
double re=0.0;
/*for(int i=0;i<=top;i++)
cout<<res[i].x<<" "<<res[i].y<<endl;*/
for(int i=0;i<=top;i++)
re+=dists(res[i],res[(i+1)%(top+1)]);
printf("%.2lf\n",re);
}
}
return 0;
}
还有一种网上的用极坐标交换的写法,标准模板
#include <iostream>
#include <math.h>
#define MaxNode 1000
int stack[MaxNode];
int top;
struct TPoint
{
int x;
int y;
};
TPoint point[MaxNode];
void swap(TPoint point[], int i, int j)
{
TPoint tmp;
tmp = point[i];
point[i] = point[j];
point[j] = tmp;
}
double multi(TPoint p1, TPoint p2, TPoint p0)
{
return double(p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
}
double distance(TPoint p1, TPoint p2)
{
return sqrt(double(p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}
//qsort的比较函数,如果要从小到大排序,则:参数1>参数2时,return1;
int cmp(const void *a, const void *b)
{
TPoint *c = (TPoint *)a;
TPoint *d = (TPoint *)b;
double k = multi(*c, *d, point[0]);
if(k <= 0) return 1; //k<0说明c在d的逆时针方向,即相对于点p0,c的极角比d大
else return -1;
}
void grahamScan(int n)
{
//Graham扫描求凸包
int u=0;
//将最左下的点调整到p[0]的位置
for(int i = 1;i <= n - 1;i++)
{
if((point[i].y < point[u].y) || (point[i].y == point[u].y && point[i].x < point[u].x))
u = i;
}
swap(point, 0, u);
//将p[1]到p[n - 1]按按极角排序,可采用快速排序
qsort(point + 1, n - 1, sizeof(point[0]), cmp);
for(int i = 0;i <= 2;i++) stack[i] = i;
top = 2;
for(int i = 3;i <= n - 1;i++)
{
while(multi(point[i], point[stack[top]], point[stack[top - 1]]) > 0)
top--;
top++;
stack[top] = i;
}
}
double length(int n)
{
//已知多边形各顶点的坐标,求其周长
double len;
int i;
len = 0;
for(i = 0;i <= n - 1;i++){
len += (distance(point[stack[i]], point[stack[(i + 1) % n]]));//别忘了模n(处理最后一个点和第一个点的距离)
}
return len;
}
int main()
{
int i, n;
while(scanf("%d", &n) && n ){
for(i = 0;i < n;i++)
scanf("%d%d", &point[i].x, &point[i].y);
if(n < 2){
printf("0.00\n");
continue;
}
if(n == 2){
printf("%.2lf\n", distance(point[0], point[1]));
continue;
}
grahamScan(n);
printf("%.2lf\n", length(top + 1));
}
return 0;
}