1. 程式人生 > >【計算幾何】【分類討論】Gym - 101243I - Land Division

【計算幾何】【分類討論】Gym - 101243I - Land Division

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