2020牛客暑期多校训练营(第三场)C.Operation Love(计算几何) 题解

题意:
按顺时针或逆时针的顺序给出这样一只手上所有的点坐标
给出的图形在大小长度上都是一样的,只是可能经过了旋转。
要求判断是左手还是右手
思路:
找到最长的一条边a(长度为9)然后再找到一条长度为8的边b,两个向量做叉乘,如果bxa>0则为右手,否则为左手。
在这里插入图片描述
代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<cmath>
using namespace std;

template<class T>inline void read(T &x){x=0;char o,f=1;while(o=getchar(),o<48)if(o==45)f=-f;do x=(x<<3)+(x<<1)+(o^48);while(o=getchar(),o>47);x*=f;}
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
#define ll long long
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repb(i,a,b) for(int i=(a);i>=b;i--)
#define INF 0x3f3f3f3f
#define cendl printf("\n")
ll gcd(ll a,ll b){ while(b^=a^=b^=a%=b); return a; }
//#define INF 0x7fffffff

const double eps = 0.001;
const int MAXN = 25;

struct point{
	double x,y; 
	point(int x=0,int y=0):x(x),y(y){}
};

inline double dis(point a,point b){//计算距离 
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

vector<point> a(20);

void solve(){
	for(int i=0;i<20;i++){
		cin>>a[i].x>>a[i].y;
	}
	//找到长为9的那条大边 
	point max1,max2;//记录最长那条边的两个端点 
	double maxlen=-1.0;//记录最长长度 
	for(int i=0;i<20;i++){
		if(maxlen<dis(a[i],a[(i+1)%20])){
			max1=a[i]; max2=a[(i+1)%20];
			maxlen = dis(max1,max2);
		}
	}
	point max3;
	for(int i=0;i<=19;i++){//找到第二长的,长为8的那条边 
		if(fabs(dis(max1,a[i])-8.0)<eps){
			max3 = a[i];
			break;
		}
		else if(fabs(dis(max2,a[i])-8.0)<eps){
			max3 = a[i];
			swap(max1,max2);//要让max1成为这两条边的交点,所以这种情况下交换max1和max@ 
			break;
		}
	}
	double chaji = (max3.x-max1.x)*(max2.y-max1.y)-(max2.x-max1.x)*(max3.y-max1.y);//做叉积判断左右手 
	if(chaji>0) cout<<"right"<<endl;
	else cout<<"left"<<endl;
}

int main(){
	int z;
	cin>>z;
	while(z--) solve();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值