Topic links: http://acm.hdu.edu.cn/showproblem.php?pid=6617
Title effect: given a convex hull \ (P \), and find the smallest \ (P \) similar and parallel to the side corresponding to the polygon, such that a given subject \ (m \) points \ (Q_I \) are the polygon included, similar to the minimum output ratio
Solution: binary answer \ (k \), consideration of how to determine the \ (P \) is amplified \ whether the (K \) times can translate this \ (m \) points so that they are within the polygon. All look as a directed line segment (counterclockwise), then \ (m \) are the points of the polygon inside the polygon when and only if they are to have left in these segments. Record of the \ (I \) edges \ (F_i \) means that if the point \ (q_ {f_i} \) on this left side, we can ensure that all points on its left side, by this \ (m after \) find points in the convex hull may be determined (O (m) \) time complexity \ \ (f_i \). So we only need to know, whether the presence of a translation vector, so that \ (m \) after translation points, all the points \ (q_ {f_i} \) are left at the \ (I \) of edges .
So we if each edge \ ((p_i, p_ {i + 1}) \), to obtain a qualified vector set \ (\ vec {A_i} \), it can be determined whether their intersection is empty to determine the current ratio \ (k \) is legitimate. Can be found in \ (\ vec {A_i} = \ {\ vec {OA} | A \ text {is on the left of} \ vec {(p_i-q_ {f_i}, p_ {i + 1} -q_ {f_i} )} \} \) represents a half-plane, then we can solve this question by seeking to pay half plane.
Note that the subject request is parallel to the corresponding sides, so we have the original pattern rotation \ (180 ^ {\ circ} \) do it again, extracted twice answer minimum output.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define N 100001 const double eps=1e-10; int sgn(double x) { if(x<-eps)return -1; if(x>eps)return 1; return 0; } struct Point { double x,y; void read(){scanf("%lf%lf",&x,&y);} Point operator +(const Point &t)const{return {x+t.x,y+t.y};} Point operator -(const Point &t)const{return {x-t.x,y-t.y};} double operator *(const Point &t)const{return x*t.y-y*t.x;} Point operator *(const double t)const{return {x*t,y*t};} Point operator /(const double t)const{return {x/t,y/t};} double ang()const{return atan2(1.0*y,1.0*x);} double length()const{return sqrt(x*x+y*y);} }p[N]; struct Line { Point p1,p2; Point isct(const Line &t)const { double a=(p2-p1)*(t.p1-p1); double b=(p2-p1)*(p1-t.p2); return (t.p1*b+t.p2*a)/(a+b); } }q[N],line[N]; Point cent; bool cmpang(const Point &p1,const Point &p2) { int tmp=sgn((p1-cent).ang()-(p2-cent).ang()); if(tmp!=0)return tmp<0; return (p1-cent).length()<(p2-cent).length(); } struct Polygon { int n; Point a[N]; void read() { scanf("%d",&n); for(int i=1;i<=n;i++) a[i].read(); } void ChangetoConvex() { for(int i=2;i<=n;i++) if(a[i].x<a[1].x || (a[i].x==a[1].x && a[i].y<a[1].y)) swap(a[1],a[i]); cent=a[1]; sort(a+2,a+n+1,cmpang); int top=2; for(int i=3;i<=n;i++) { while(top>=2 && (a[top]-a[top-1])*(a[i]-a[top])<=0)top--; a[++top]=a[i]; } n=top; } }P,Q; int T,nxt[N],pre[N],f[N]; bool check(int i,Point A,Point B) { return sgn((B-A)*(Q.a[pre[i]]-Q.a[i]))>=0 && sgn((B-A)*(Q.a[nxt[i]]-Q.a[i]))>=0; } bool Left(const Point &p,const Line &l){return sgn((l.p2-l.p1)*(p-l.p1))==1;} bool HalfPlane(int n) { int h=1,t=1; q[1]=line[1]; for(int i=2;i<=n;i++) { while(h<t && !Left(p[t-1],line[i]))t--; while(h<t && !Left(p[h],line[i]))h++; if(sgn((q[t].p2-q[t].p1)*(line[i].p2-line[i].p1))==0) q[t]=Left(q[t].p1,line[i])?q[t]:line[i]; else q[++t]=line[i]; if(h<t)p[t-1]=q[t].isct(q[t-1]); } while(h<t && !Left(p[t-1],q[h]))t--; if(t-h<=1)return false; p[t]=q[t].isct(q[h]); double ans=0; for(int i=h;i<=t;i++) ans+=p[i]*p[(i+1-h)%(t-h+1)+h]; return sgn(ans)>=0; } bool check(double k) { for(int i=1;i<=P.n;i++) line[i]={P.a[i]*k-Q.a[f[i]],P.a[i%P.n+1]*k-Q.a[f[i]]}; return HalfPlane(P.n); } double solve() { int j=1; for(int i=1;i<=P.n;i++) { while(!check(j,P.a[i],P.a[i%P.n+1]))j=nxt[j]; f[i]=j; } double l=0,r=1e9,mid; while(l+eps<r) { mid=(l+r)*0.5; if(check(mid))r=mid; else l=mid; } return l; } void init() { double ans=1e18; P.read(),Q.read(); if(Q.n==1){printf("%.6f\n",0.0);return;} P.ChangetoConvex(); Q.ChangetoConvex(); for(int i=1;i<=Q.n;i++) nxt[i]=i%Q.n+1,pre[i%Q.n+1]=i; ans=min(ans,solve()); for(int i=1;i<=P.n;i++) P.a[i]=P.a[i]*(-1.0); ans=min(ans,solve()); printf("%.6f\n",ans); } int main() { scanf("%d",&T); while(T--)init(); }
Description of \ (\ vec {A_i} \): The set point \ (q_ {f_i} \) of \ (Q \), then \ (\ vec {OA} \) satisfy the origin \ (O \) translational \ (\ vec {OA} \), he has left in the segment \ (\ vec {(p_i-Q, p_ {i + 1} -Q)} \) a. Therefore origin \ (O \) after translation \ (\ vec {OA} \), then the translation \ (\ vec {OQ} \), which is able to meet the directed line segment \ (\ vec {(p_i, p_ { left i + 1})} \) a. And \ (O + \ vec {OA} + \ vec {OQ} = O + \ vec {OQ} + \ vec {OA} = Q + \ vec {OA} \), thus \ (Q \) translation \ (\ VEC {OA} \) is able to meet the requirements.