2020牛客网暑期多校训练营Operation Love(计算几何,叉积)

题目

传送门

题目大意

爱丽丝是机器人社会的美人。 这么多机器人想嫁给她恐怖的机翻。 爱丽丝决定嫁给可以解决以下难题的机器人:
首先,爱丽丝右手掌的形状如下:
在这里插入图片描述

爱丽丝的左手掌形状与她的右手掌对称。
在这个难题中,爱丽丝将给挑战者她手掌的许多手印。 挑战者必须正确告诉Alice每个手印是她的左手掌还是右手掌。 请注意,爱丽丝手掌的手印由其2D平面坐标按顺时针或逆时针顺序给出。 并且形状可以旋转和平移。 但是形状不会被放大或缩小。
尽管您不是机器人,但您对解决难题很感兴趣。 请尝试解决这个难题。

分析

由于手掌大小不变,各边为固定值,所以我们可以从边入手。
但这题的输入方向不定(顺时针读入或逆时针读入),手掌方向不定(朝上朝下朝左朝右),并不能简单地根据边长来判断,所以考虑用平面几何的向量来判断。
首先先找到掌根(最长边长度为9),然后甭管这是顺时针还是逆时针,直接看下一条边是不是是8还是6,接着把8或6与9叉积判断结果正负即可。

在这里插入图片描述
如:若下一条边为6且叉积为负就是右手,为正就是左手;若下一条边为8且叉积为负就是左手,为正就是右手。
最后要注意的是:计算几何一定要注意精度!差的绝对值要与eps比较

代码

#include<bits/stdc++.h>
using namespace std;
const double eps=0.1;

struct point{
    double x,y;
    point(){}
    point(double _x,double _y){
        x=_x;
        y=_y;
    }
    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;
    }
    void transXY(double B){
        double tx = x,ty = y;
        x = tx*cos(B)-ty*sin(B);
        y = tx*sin(B)+ty*cos(B);
    }
    void input(){
        scanf("%lf%lf",&x,&y);
    }
};
double dist(point a,point b){
  return sqrt((a-b)*(a-b));
}
point a[25];
int main()
{
    int t;scanf("%d",&t);
    while(t--){
        for(int i=0;i<20;i++) a[i].input();
        int fl=0;//1 left   2 right
        for(int i=0;i<20;i++){
            if(fabs(dist(a[i],a[(i+1)%20])-9)<=eps){
                point x=a[i],y=a[(i+1)%20],z=a[(i+2)%20];
                if((fabs(dist(y,z)-6)<=eps&&((y-x)^(z-y))<0)||(fabs(dist(y,z)-8)<=eps&&((y-x)^(z-y))>0)){
                    fl=2;
                }
                else if((fabs(dist(y,z)-6)<=eps&&((y-x)^(z-y))>0)||(fabs(dist(y,z)-8)<=eps&&((y-x)^(z-y))<0)){
                    fl=1;
                }
                break;
            }
        }
        if(fl==1) printf("left\n");
        else printf("right\n");
    }
}


----原创文章,仅供参考

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值