Minkowski和
来源:互联网 发布:bender软件 编辑:程序博客网 时间:2024/04/27 17:24
两个凸集的和(每两个不同集的x,y分别相加得新点)为凸集。
将两个凸集按同样时针求向量,极角排序后按向量走既得新凸集(但还需对应点平移)。
应用:求两凸集距离。
area
求新凸集面积。
不需平移,直接叉积。
这道题证明二分快排是可以卡的。
#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <ctime>struct point{ long long x,y,c;};const double eps=1e-6;point a[300000],b[3][300000],p[300000];int n,m,tot,t[3],st[3][300000];int cmper(const void *i,const void *j){ point *p=(point *)i,*q=(point *)j; if (0==(p->y - q->y)) return (p->x-q->x);// if (p->y == q->y) return p->x - q->x; return p->y-q->y;}inline long long cross(point e,point r){ return ((e.x*r.y)-(e.y*r.x));}int check(int c,int i,int j,int k){ point u,v,w; u=a[i],v=a[j],w=a[k]; point e,r; e.x=v.x-u.x,e.y=v.y-u.y; r.x=w.x-u.x,r.y=w.y-u.y; long long kk=cross(e,r); return (kk>=0) ? 1 : 0;}void work(int c,int s){ qsort(a+1,s,sizeof(a[1]),cmper); memset(st[c],0,sizeof(st[c])); t[c]=1;st[c][t[c]]=1; int i,k; for (i=2;i<=s;i++) { for (;(t[c]>1)&&(check(c,st[c][t[c]-1],st[c][t[c]],i));t[c]--) ; st[c][++t[c]]=i; } k=t[c]; for (i=s-1;i>0;i--) { for (;(t[c]>k)&&(check(c,st[c][t[c]-1],st[c][t[c]],i));t[c]--) ; st[c][++t[c]]=i; } if (s>1) t[c]--; }void init(){ scanf("%d%d\n",&n,&m); int i; for (i=1;i<=n;i++) { scanf("%I64d%I64d",&a[i].x,&a[i].y);// b[1][i]=a[i]; } scanf("\n"); work(1,n); for (i=1;i<=n;i++) b[1][i]=a[i]; memset(a,0,sizeof(a)); for (i=1;i<=m;i++) { scanf("%I64d%I64d",&a[i].x,&a[i].y);// b[2][i]=a[i]; } scanf("\n"); work(2,m); for (i=1;i<=m;i++) b[2][i]=a[i]; } long long equ(long long x){ if ((x>-eps)&&(x<eps)) return 1; return 0;} void doit(int c){ int i; for (i=2;i<=t[c];i++) { tot++; p[tot].x=b[c][st[c][i]].x-b[c][st[c][i-1]].x; p[tot].y=b[c][st[c][i]].y-b[c][st[c][i-1]].y; if ((p[tot].x>0)&&((p[tot].y>0)||(equ(p[tot].y)))) p[tot].c=1; if (((p[tot].x<0)||(equ(p[tot].x)))&&(p[tot].y>0)) p[tot].c=2; if ((p[tot].x<0)&&((p[tot].y<0)||(equ(p[tot].y)))) p[tot].c=3; if (((p[tot].x>0)||(equ(p[tot].x)))&&(p[tot].y<0)) p[tot].c=4; } tot++; p[tot].x=b[c][st[c][1]].x-b[c][st[c][i-1]].x; p[tot].y=b[c][st[c][1]].y-b[c][st[c][i-1]].y; if ((p[tot].x>0)&&((p[tot].y>0)||(equ(p[tot].y)))) p[tot].c=1; if (((p[tot].x<0)||(equ(p[tot].x)))&&(p[tot].y>0)) p[tot].c=2; if ((p[tot].x<0)&&((p[tot].y<0)||(equ(p[tot].y)))) p[tot].c=3; if (((p[tot].x>0)||(equ(p[tot].x)))&&(p[tot].y<0)) p[tot].c=4; }inline int chek(point a,point b){ if (a.c<b.c) return 1 ; else if (a.c>b.c) return 0; long long k=cross(a,b);// if (k<=0) return 0; if (k>0) return 1; return 0;}void qs(int l,int r){ int i=l,j=r; point x=p[rand () % (r - l + 1) + l],c;// long long xx=cross(x,x); for (;i<=j;) { for (;chek(p[i],x);i++) ; for (;chek(x,p[j]);j--) ; if (i<=j) { c=p[i],p[i]=p[j],p[j]=c; i++,j--; } } if (i<r) qs(i,r); if (l<j) qs(l,j); }int cmp(const void *i,const void *j){ point a=*(point*)i,b=*(point*)j; if (a.c<b.c) return -1 ; else if (a.c>b.c) return 1; long long k=cross(a,b);// if (k<=0) return 0; if (k>0) return -1; return 1;}void make(){// qs(1,tot); qsort(p+1,tot,sizeof(p[1]),cmp) ; int i; long long ans=0; point u,v; u.x=0,u.y=0; for (i=1;i<=tot;i++) { v.x=u.x+p[i].x; v.y=u.y+p[i].y; ans+=cross(u,v); u=v; } if (ans<eps) ans=-ans; printf("%I64d\n",ans); }int main(){ freopen("area.in","r",stdin); freopen("area.out","w",stdout); srand( int(time(NULL))); init(); tot=0; doit(1); doit(2); make(); return 0;}
- Minkowski和
- Inequalities - Minkowski's inequality
- . 和 ->
- || 和&&
- .和::
- “?”和“!”
- #和##
- && 和 ||
- 、和
- #和##
- .//和..//
- 和
- ?和\?
- ./ 和 ../
- #和##
- #、和##
- #和##
- *和&
- 程序设计建议
- 对于实现Java平台的三种方式的详细解析
- Linux下SRAM的读写
- 极角排序
- 中人网面试经经历(感觉公司很垃圾)
- Minkowski和
- android 修改host 文件
- 【杂谈】二厶可可肉搜索测试,Google PK 百度
- Java常用的设计模式
- 半平面交
- 清空tomcat缓存
- hudson的使用方法
- MM
- Linux下socket编程简介