hdu 6617 Enveloping Convex

貌似数据是错的。。不管数据对不对,至少这是个比较强的计算几何。

题意:给定n个点的凸多边形A,需要找到最小的与A相似的多边形A’,并且A’与A的对应边平行,使得A’包含平面上m个点。输出最小的相似比。

显然先对m个点凸包,然后二分相似比。然后要判断凸包A能否包含凸包B。一个观察是临界情况B的一条边卡着A的两条边,可以枚举卡的边来确定相对位置,判断其他点是否在A内部,需要旋转卡壳来加速。不幸的是数据范围比较大,算交点时会有很大的精度误差。正确做法比较直接,先算出A的边在B上对应的点,然后做个差向内平移一段距离,半平面交判断是否为空即可。(既然有闵科夫斯基和,当然也有差了2333)

一个坑点是与A中心对称的图形也满足条件,所以还要翻过来再算一次。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3.  
  4. #define inc(i,n) for (int i=0;i<n;i++)
  5.  
  6. typedef double db;
  7. const db PI=acos(-1);
  8. const db eps=1e-11, inf=1e12;
  9.  
  10. bool eq(db x){return fabs(x)<eps;}
  11. int sgn(db x){
  12.     if (x<=-eps) return -1;
  13.     return x>=eps;
  14. }
  15.  
  16. #define Vec const vec &
  17. #define Point const point &
  18. struct vec{
  19.     db x,y;
  20.     vec():x(0),y(0){}
  21.     vec(db x, db y):x(x),y(y){} //[i] init-list is easier to use in c++1x
  22.     vec(db theta):x(cos(theta)),y(sin(theta)){}
  23.  
  24.     bool operator==(Vec v) const{return eq(x-v.x) && eq(y-v.y);}
  25.     db ang() const{return atan2(y,x);}
  26.  
  27.     vec operator+(Vec v) const{return vec(x+v.x,y+v.y);}
  28.     vec operator-(Vec v) const{return vec(x-v.x,y-v.y);}
  29.     vec operator*(db a) const{return vec(x*a,y*a);}
  30.     vec operator/(db a) const{return vec(x/a,y/a);}
  31.  
  32.     db operator|(Vec v) const{return x*v.x+y*v.y;}
  33.     db operator&(Vec v) const{return x*v.y-y*v.x;}
  34.     db operator!() const{return sqrt(x*x+y*y);} 
  35.  
  36.     bool operator<(Vec v) const{return x==v.x?y<v.y:x<v.x;}
  37.  
  38.     void rd(){scanf("%lf%lf",&x,&y);}
  39.     void prt(){printf("%f %f\n",x,y);}
  40.     vec std(){
  41.         return (*this)/!(*this);
  42.     }
  43.     friend ostream& operator<<(ostream &o, Vec v){return o<<v.x<<','<<v.y;}
  44. };
  45. typedef vec point;
  46. db cross(Vec a, Vec b, Vec c){
  47.     return b-a&c-a;
  48. }
  49.  
  50. point lineInt(Point p, Vec vp, Point q, Vec vq){
  51.     db t=(vq & p-q)/(vp&vq);
  52.     return p+vp*t;
  53. }
  54.  
  55. int convex(point *p, int n, point *ans){
  56.     sort(p,p+n);
  57.     int m=0;
  58.     for (int i=0;i<n;i++){
  59.         while (m>1 && cross(ans[m-2],ans[m-1],p[i])<=eps) m--;
  60.         ans[m++]=p[i];
  61.     }
  62.     int k=m;
  63.     for (int i=n-2;i>=0;i--){
  64.         while (m>k && cross(ans[m-2],ans[m-1],p[i])<=eps) m--;
  65.         ans[m++]=p[i];
  66.     }
  67.     if (n>1) m--; //p[0]==p[m]
  68.     return m;
  69. }
  70.  
  71. const int N=100010;
  72.  
  73. point p[N],q0[N],q[N],p0[N],q1[N],vl,vr;
  74. int n,m;
  75.  
  76. struct line{
  77. 	point p; vec v;
  78. };
  79.  
  80. bool onleft(point p, const line &l){return sgn(l.v&p-l.p)>0;}
  81. line Q[N<<1]; //deque of lines
  82. point T[N<<1]; //deque of points(result)
  83. bool halfplaneInt(line *l, int n){
  84. 	int head=0,tail=0; //rangeof Q:[head,tail] ; range of T: [head, tail)
  85. 	Q[0]=l[0];
  86. 	for (int i=1;i<n;i++){
  87. 		while (head<tail && !onleft(T[tail-1],l[i])) tail--;
  88. 		while (head<tail && !onleft(T[head],l[i])) head++;
  89. 		Q[++tail]=l[i];
  90. 		if (eq(Q[tail].v&Q[tail-1].v)){ //same direction
  91. 			--tail;
  92. 			if (onleft(l[i].p,l[i])) Q[tail]=l[i]; //replace righter line
  93. 		}
  94. 		if (head<tail) //get point
  95. 			T[tail-1]=lineInt(Q[tail-1].p,Q[tail-1].v,Q[tail].p,Q[tail].v);		
  96. 	}
  97. 	while (head<tail && !onleft(T[tail-1],Q[head])) tail--; 
  98. 	if (head>=tail-1) return 0;  //m<3, no available area
  99. 	return 1;
  100. }
  101.  
  102. line pl[N];
  103. bool chk(db r){
  104.     for (int i=0;i<n;i++){
  105.     	vec v1=p[i]*r-q1[i];
  106.     	vec v2=p[i+1]*r-q1[i];
  107.     	pl[i]={v1,v2-v1};
  108. 	}
  109.     return halfplaneInt(pl,n);
  110. }
  111.  
  112. int main(){
  113. 	//freopen("14160.in","r",stdin);
  114.     int T; scanf("%d",&T);
  115.     while (T--){
  116.         scanf("%d",&n);
  117.         db gmax=0;
  118.         inc(i,n) p0[i].rd(),gmax=max(gmax,max(p0[i].x,p0[i].y));
  119.         scanf("%d",&m);
  120.         inc(i,m) q0[i].rd(),gmax=max(gmax,max(q0[i].x,q0[i].y));
  121.         //inc(i,n) p0[i]=p0[i]/gmax; inc(i,m) q0[i]=q0[i]/gmax;
  122.         n=convex(p0,n,p); m=convex(q0,m,q);
  123.         p[n]=p[0];
  124.         /*
  125.         int mpi; db mpd=10;
  126.         for (int i=0;i<n;i++){
  127.             db diff=fabs((p[i+1]-p[i]).ang()-(p[i]-p[(i+n-1)%n]).ang());
  128.             if (diff<mpd){
  129.                 mpd=diff;
  130.                 mpi=i;
  131.             }
  132.         }
  133.         rotate(p,p+mpi,p+n);*/
  134.         q[m]=q[0];
  135.         q[m+1]=q[1];
  136.         p[n]=p[0];
  137.         db ans1=1e10;
  138. 		for (int _=0;_<2;_++){
  139. 			for (int i=0,des=0;i<n;i++){
  140. 				while (!((p[i+1]-p[i]&q[des+1]-q[des])>=0 && (p[i+1]-p[i]&q[des]-q[(des-1+m)%m])<=0)) des=(des+1)%m;
  141. 				q1[i]=q[des];
  142. 			}
  143. 	        db l=1e-7, r=1e8;
  144. 	        for (int i=0;i<60;i++){
  145. 	            db mid=(l+r)/2;
  146. 	            if (chk(mid)) r=mid;
  147. 	            else l=mid;
  148. 	        }
  149. 	        ans1=min(ans1,l);
  150. 			inc(i,n+1) p[i]=(vec){0,0}-p[i];
  151. 		}
  152.         printf("%.10lf\n",ans1);
  153.     }
  154.     return 0;
  155. }

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注