【計算幾何】【分類討論】Gym - 101243I - Land Division
阿新 • • 發佈:2017-10-04
log clas algo 答案 cto esp turn 端點 name
題意:給你一個n個點的凸包,讓你切一刀,使得它變成一個m邊形和一個K邊形,問你切的這一刀最短是多少。
如果m+K==n+4,那麽一定切在兩條邊上,但是由於兩個線段間的最短距離,至少會經過一條線段的一個端點,於是可以枚舉其中一條邊,然後算出另一條邊,然後枚舉4個端點到對面線段的距離,取最小值即可。
如果m+K==n+3,那麽一定切在一個點和一個邊上,可以枚舉那個點,算出順時針和逆時針方向切到的那條邊是誰,然後更新答案。
如果m+K==n+2,那麽一定切在兩個點上,可以枚舉其中一個點,算出順時針和逆時針方向切到的另外一個點是誰,然後更新答案。
其他情況無解。
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; double ans=99999999999999.0; struct Point{ int x,y; Point(const int &x,const int &y){ this->x=x; this->y=y; } Point(){} double Length(){ return sqrt((double)x*(double)x+(double)y*(double)y); } void read(){ scanf("%d%d",&x,&y); } }p[105]; typedef Point Vector; Vector operator - (const Point &a,const Point &b){ return Vector(a.x-b.x,a.y-b.y); } int Dot(const Vector &a,const Vector &b){ return a.x*b.x+a.y*b.y; } int Cross(const Vector &a,const Vector &b){ return a.x*b.y-a.y*b.x; } int n,m,K; double DisToSegment(Point P,Point A,Point B) { Vector v1=B-A,v2=P-A,v3=P-B; if(Dot(v1,v2)<=0) return v2.Length(); else if(Dot(v1,v3)>0) return v3.Length(); else return fabs((double)Cross(v1,v2))/v1.Length(); } double Min(double a,double b,double c,double d,double e){ return min(a,min(b,min(c,min(d,e)))); } //double Min(double a,double b,double c){ // return min(a,min(b,c)); //} int main(){ freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); scanf("%d%d%d",&n,&m,&K); for(int i=0;i<n;++i){ p[i].read(); } if(m+K==n+4){ if(m==3 || m==n+1){ puts("0.000"); return 0; } for(int i=0;i<n;++i){ int j=(i+m-2)%n; ans=Min(ans,DisToSegment(p[i],p[j],p[(j+1)%n]), DisToSegment(p[(i+1)%n],p[j],p[(j+1)%n]), DisToSegment(p[j],p[i],p[(i+1)%n]), DisToSegment(p[(j+1)%n],p[i],p[(i+1)%n])); } printf("%.3lf\n",ans); } else if(m+K==n+3){ for(int i=0;i<n;++i){ int j=(i+m-2)%n; ans=min(ans,DisToSegment(p[i],p[j],p[(j+1)%n])); j=(i-(m-2)+n)%n; ans=min(ans,DisToSegment(p[i],p[j],p[(j-1+n)%n])); } printf("%.3lf\n",ans); } else if(m+K==n+2){ for(int i=0;i<n;++i){ int j=(i+m-1)%n; ans=min(ans,(p[i]-p[j]).Length()); j=(i-(m-1)+n)%n; ans=min(ans,(p[i]-p[j]).Length()); } printf("%.3lf\n",ans); } else{ puts("-1"); } return 0; }
【計算幾何】【分類討論】Gym - 101243I - Land Division