C. Operation Love(维护凸包/多边形面积判断顺时针逆时针) 2020牛客暑期多校训练营(第三场)

题意:
一个手掌图形,可以旋转平移,但不会改变大小形状。求这个手掌是左手还是右手

思路:
sb了很久。其实判断是顺时针还是逆时针,然后看出现8,9还是出现9,8。
一开始在想用凸包维护角度,看上面两个角度区间,但是不熟悉板子,所以没搞好。
其实根据叉积性质,用求多边形面积方法,看正负就可以判断是顺时针还是逆时针。

用面积正负代表顺时针逆时针

#include 
#include 
#include 
#include 

using namespace std;

const double eps = 1e-8;
const double PI = acos(-1);
struct point
{
    double x,y;
    point(){}
    point(double _x,double _y)
    {
        x = _x;y = _y;
    }
    point operator+(point a)
    {
        return point(x + a.x,y + a.y);
    }
    point operator-(point a)
    {
        return point(x - a.x,y - a.y);
    }
    double operator*(point a)
    {
        return x * a.y - y * a.x;
    }
    
}p[30];

double dis(point a,point b) {
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

bool dcmp(double x,double y)
{
    if(x - y < eps && x - y > -eps)
        return 0;
    if(x - y > 0)return 1;
    return -1;
}

bool cal(int cnt)
{
    double ans = 0;
    for(int i = 0;i <= cnt - 1;i++)
    {
        ans += (p[i] - p[0]) * (p[i + 1] - p[0]);
    }
    return ans > 0;
}

int main() {
    int T;scanf("%d",&T);
    while(T--) {
        for(int i = 0;i < 20;i++) {
            scanf("%lf%lf",&p[i].x,&p[i].y);
            p[i + 20] = p[i];
        }
        int res = cal(20); //为1代表逆时针
        for(int i = 0;i <= 37;i++) {
            double d1 = dis(p[i],p[i + 1]);
            double d2 = dis(p[i + 1],p[i + 2]);
            if(fabs(d1 - 9) < 0.1 && fabs(d2 - 8) < 0.1) {
                if(res) printf("right\n");
                else printf("left\n");
                break;
            }
            if(fabs(d1 - 8) < 0.1 && fabs(d2 - 9) < 0.1) {
                if(res) printf("left\n");
                else printf("right\n");
                break;
            }
        }
    }
    return 0;
}

维护凸包直接得到逆时针序列
板子源于网络,感谢原作者。

#include
#include
#include
#include
#include 
using namespace std;
 
struct Point
{
    double x,y;
    Point(){}    //构造函数
    Point(double xx,double yy)
    {
        x = xx;
        y = yy;
    }
    Point operator-(const Point a)const
    {
        return Point(x-a.x,y-a.y);
    }
}p[11000],ch[11000];    //原序列和凸包序列
 
bool cmp(Point a,Point b)
{   //点排序
    if(a.x == b.x)  return a.y < b.y;
    return a.x < b.x;
}
double det (Point a, Point b)
{
    return a.x * b.y - a.y * b.x;
}
double dis(Point a,Point b) {
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
int ConvexHull(Point *p,int n,Point *ch)
{   //构造凸包
    sort(p,p+n,cmp);
    int m=0;
    //a叉b 夹角代表a转向b 若a顺时针转才能与b重合 则该值<0
    //可用OA(0,1)与OB(1,0)举例 原到现需顺时针转
    for(int i=0;i<n;i++)
    {
        while(m>1&&det(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)m--;
        ch[m++]=p[i];
    }
    int k=m;
    for(int i=n-2;i>=0;i--)
    {
        while(m>k&&det(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)m--;
        ch[m++]=p[i];
    }
    if(n>1)m--;
    return m;
}
 
int main() {
    int T;scanf("%d",&T);
    while(T--) {
        for(int i = 0;i < 20;i++) {
            scanf("%lf%lf",&p[i].x,&p[i].y);
        }
        int num = ConvexHull(p, 20, ch);
        ch[num++] = ch[0];
        ch[num++] = ch[1];
        for(int i = 0;i < num - 2;i++) {
            double d1 = dis(ch[i],ch[i + 1]);
            double d2 = dis(ch[i + 1],ch[i + 2]);
            if(fabs(d1 - 8) < 0.1 && fabs(d2 - 9) < 0.1) {
                printf("left\n");
                break;
            }
            if(fabs(d1 - 9) < 0.1 && fabs(d2 - 8) < 0.1) {
                printf("right\n");
                break;
            }
        }
    }
    return 0;
}

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