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

题意:
按顺时针或逆时针的顺序给出这样一只手上所有的点坐标
给出的图形在大小长度上都是一样的,只是可能经过了旋转。
要求判断是左手还是右手
思路:
找到最长的一条边a(长度为9)然后再找到一条长度为8的边b,两个向量做叉乘,如果bxa>0则为右手,否则为左手。
2020牛客暑期多校训练营(第三场)C.Operation Love(计算几何) 题解_第1张图片
代码:

#include
#include
#include
#include
#include
#include
#include
#include
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();
}

你可能感兴趣的:(计算几何)