对于第一个数据:
0 1
0 2
0 3
0 4
...
我的代码,维护下凸包时很顺畅,但是维护上凸包时,会把所有除了一号点以外的点都弹出栈,最后栈中只剩下第一个点。
究其原因,我的代码会判断两个横坐标都是 0 的向量的叉积小于等于 0。这会导致,维护上凸包的时候所有点都被弹出。
如果将代码中的小于等于号换成小于号可以解决,但是栈中会加入许多无用点(类似 (0,1),(0,2),(0,3),(0,4)
,但事实上只用加入 (0,1),(0,4)
)。
应该怎么样修改代码才能解决这个问题
#include<bits/stdc++.h>
#define rep(i,x,y) for(int i=x;i<=y;++i)
#define per(i,x,y) for(int i=x;i>=y;--i)
#define lod long double
using namespace std;
const int n7=201234;
struct dino{
lod x,y;
friend bool operator < (dino p,dino q){return p.x==q.x?p.y<q.y:p.x<q.x;}
}a[n7];
int n,top,sak[n7];lod ans;
int rd(){
int shu=0;bool fu=0;char ch=getchar();
while( !isdigit(ch) ){if(ch=='-')fu=1;ch=getchar();}
while( isdigit(ch) )shu=(shu<<1)+(shu<<3)+ch-'0',ch=getchar();
return fu?-shu:shu;
}
lod cross(dino p,dino q){return p.x*q.y-p.y*q.x;}
dino vet(int p,int q){return (dino){a[q].x-a[p].x,a[q].y-a[p].y};}
int main(){
n=rd();
rep(i,1,n)scanf("%Lf%Lf",&a[i].x,&a[i].y);
sort(a+1,a+n+1);
top=2,sak[1]=1,sak[2]=2;
rep(i,3,n){
while(top>1 && cross(vet(sak[top-1],sak[top]),vet(sak[top-1],i))<=0 )top--;
top++,sak[top]=i;
}
top++,sak[top]=n-1;
per(i,n-2,1){
while(top>1 && cross(vet(sak[top-1],sak[top]),vet(sak[top-1],i))<=0 )top--;
top++,sak[top]=i;
}
top++,sak[top]=sak[1];
rep(i,2,top){
dino tmp=vet(sak[i-1],sak[i]);
ans=ans+sqrt(tmp.x*tmp.x+tmp.y*tmp.y);
}
printf("%.2Lf",ans);
return 0;
}