Andrew怎么跑出点数最小解
查看原帖
Andrew怎么跑出点数最小解
99623
BlankAo楼主2021/11/26 16:32

对于第一个数据:

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;
}
2021/11/26 16:32
加载中...