• 【计算几何】【分类讨论】Gym


    题意:给你一个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
    ",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
    ",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
    ",ans);
    	}
    	else{
    		puts("-1");
    	}
    	return 0;
    }
  • 相关阅读:
    Python微信机器人
    Jumpserver开源跳板机系统介绍
    Django---django-rest-framework(drf)-luffycity projects
    Linux-Mysql 遗忘密码如何解决?
    up line
    linux
    vue中computed(计算属性)
    input框在浏览器上显示一个叉,去掉方法
    如何通过命令行来克隆git
    手机抓包fiddler配置及使用教程
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7625790.html
Copyright © 2020-2023  润新知