BZOJ 1007 [HNOI2008]水平可见直线 ——计算几何
用了trinkle的方法,半平面交转凸包。
写了一发,既没有精度误差,也很好写。
#include <map> #include <ctime> #include <cmath> #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i>=k;--i) #define ll long long struct Vector{ int x,y; void print() { printf("Vector - > (%d,%d)\n",x,y); } }; struct Point{ int x,y; int id; void print() { printf("Point ID %d (%d,%d)\n",id,x,y); } }; Vector operator - (Point a,Point b) {Vector ret;ret.x=a.x-b.x;ret.y=a.y-b.y;return ret;} ll operator * (Vector a,Vector b) {return (ll)a.x*b.y-(ll)a.y*b.x;} int n,top=0; Point a[50005],sta[50005]; bool cmp(Point a,Point b) {return a.x==b.x?a.y<b.y:a.x<b.x;} bool cmp2(Point a,Point b) {return a.id<b.id;} void Andrew() { F(i,1,n) if (a[i].x!=a[i-1].x){ while (top>=2&&(sta[top]-sta[top-1])*(a[i]-sta[top])<=0) top--; sta[++top]=a[i]; } sort(sta+1,sta+top+1,cmp2); F(i,1,top) printf("%d ",sta[i].id); printf("\n"); } void Finout() { freopen("bzoj_1007.in","r",stdin); freopen("bzoj_1007.out","w",stdout); } int main() { // Finout(); scanf("%d",&n); F(i,1,n) { scanf("%d%d",&a[i].x,&a[i].y); a[i].y=-a[i].y; a[i].id=i; } sort(a+1,a+n+1,cmp); Andrew(); }