欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

牛客多校3 - Operation Love(几何+叉积确定三点顺逆)

程序员文章站 2022-06-03 19:28:51
...

题目链接:点击查看

题目大意:在平面直角坐标系中给出一只手的轮廓,需要判断是左手还是右手

题目分析:因为这些点在给出时不能确定时顺时针还是逆时针给出,所以我们需要自己来判断,这里存一下给出三点判断顺时针还是逆时针的板子(其实就是个叉积计算三角形面积的应用),当判断出给出的图形是顺时针还是逆时针输入的时候,无非只有四种情况,分类讨论一下就好了,这里我选择的是最底下的长度为 9 的边和两侧长度分别为 6 和 8 的边讨论

牛客多校3 - Operation Love(几何+叉积确定三点顺逆)

因为题目给出的数据误差较大,所以在比较大小的时候,要么eps设的大一点,或者可以干脆直接比较两条边的相对长度大小就好了,因为任意两边的距离之差还是蛮大的

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
using namespace std;

typedef long long LL;

typedef unsigned long long ull;

const int inf=0x3f3f3f3f;

const int N=2e6+100;

const double eps = 1e-8;

int sgn(double x){
	if(fabs(x) < eps)return 0;
	if(x < 0)return -1;
	else return 1;
}

struct Point{
	double x,y;
	Point(){}
	Point(double _x,double _y){
		x = _x;
		y = _y;
	}
	void input(){
		scanf("%lf%lf",&x,&y);
	}
	void output(){
		printf("%.2f %.2f\n",x,y);
	}
	bool operator == (Point b)const{
		return sgn(x-b.x) == 0 && sgn(y-b.y) == 0;
	}
	bool operator < (Point b)const{
		return sgn(x-b.x)== 0?sgn(y-b.y)<0:x<b.x;
	}
	Point operator -(const Point &b)const{
		return Point(x-b.x,y-b.y);
	}
	//叉积
	double operator ^(const Point &b)const{
		return x*b.y - y*b.x;
	}
	//点积
	double operator *(const Point &b)const{
		return x*b.x + y*b.y;
	}
	//返回长度
	double len(){
		return hypot(x,y);//库函数
	}
	//返回长度的平方
	double len2(){
		return x*x + y*y;
	}
	//返回两点的距离
	double distance(Point p){
		return hypot(x-p.x,y-p.y);
	}
	Point operator +(const Point &b)const{
		return Point(x+b.x,y+b.y);
	}
	Point operator *(const double &k)const{
		return Point(x*k,y*k);
	}
	Point operator /(const double &k)const{
		return Point(x/k,y/k);
	}
	//`计算pa  和  pb 的夹角`
	//`就是求这个点看a,b 所成的夹角`
	//`测试 LightOJ1203`
	double rad(Point a,Point b){
		Point p = *this;
		return fabs(atan2( fabs((a-p)^(b-p)),(a-p)*(b-p) ));
	}
	//`化为长度为r的向量`
	Point trunc(double r){
		double l = len();
		if(!sgn(l))return *this;
		r /= l;
		return Point(x*r,y*r);
	}
	//`逆时针旋转90度`
	Point rotleft(){
		return Point(-y,x);
	}
	//`顺时针旋转90度`
	Point rotright(){
		return Point(y,-x);
	}
	//`绕着p点逆时针旋转angle`
	Point rotate(Point p,double angle){
		Point v = (*this) - p;
		double c = cos(angle), s = sin(angle);
		return Point(p.x + v.x*c - v.y*s,p.y + v.x*s + v.y*c);
	}
}point[30];
//判断三角形顶点的方向。返回1表示顺时针,0表示三点共线,-1表示逆时针。
int ccw(Point a, Point b, Point c) 
{
	double x1 = a.x, y1 = a.y;
	double x2 = b.x, y2 = b.y;
	double x3 = c.x, y3 = c.y;	
	double v = (x2-x1)*(y3-y1)-(x3-x1)*(y2-y1);
	if(v<0)
		return 1;
	else
		return -1;
}

int main()
{
#ifndef ONLINE_JUDGE
//	freopen("data.in.txt","r",stdin);
//	freopen("data.out.txt","w",stdout);
#endif
//	ios::sync_with_stdio(false);
	int w;
	cin>>w;
	while(w--)
	{
		int n=20;
		for(int i=0;i<n;i++)
			point[i].input();
		int mark=n-1;
		double mmax=point[0].distance(point[n-1]);
		for(int i=0;i<n-1;i++)
		{
			if(point[i].distance(point[i+1])>mmax)
			{
				mmax=point[i].distance(point[i+1]);
				mark=i;
			}
		}
		Point A=point[((mark-1)%n+n)%n],B=point[mark],C=point[(mark+1)%n],D=point[(mark+2)%n];
		if(sgn(A.distance(B)<C.distance(D)))
		{
			if(ccw(A,B,C)==-1)
				puts("right");
			else
				puts("left");
		}
		else
		{
			if(ccw(A,B,C)==-1)
				puts("left");
			else
				puts("right");
		}
	}




    return 0;
}

 

相关标签: 几何