CF1017E The Supersonic Rocket(平面凸包+KMP)

版权声明:博主是菜鸡,但转的时候还是说一声吧 https://blog.csdn.net/qq_37666409/article/details/81568208

原题传送门:Codeforces 1017E

洛谷博客传送门:洛咕

题目大意就是让你求两个凸包,然后验证它们是否旋转同构

旋转同构其实类似字符串的循环同构

所以将凸包变成线段-夹角-线段-夹角……的数列形式

其中一个倍长,另一个kmp匹配即可

注意,这时候凸包的边上不能有点!

#include <bits/stdc++.h>
#define eps 1e-8
#define delta 0.98
#define Get(a, b) atan2(a, b)
using namespace std;

const int MAXN = 100100;

struct Point {
    double x, y;
    Point () {}
    Point (double _x, double _y) : x(_x), y(_y) {}
};

typedef Point Vector;
typedef Point Polygon[MAXN];

template <typename T> inline void read(T &x) {
    int c = getchar();
    bool f = false;
    for (x = 0; !isdigit(c); c = getchar()) {
        if (c == '-') {
            f = true;
        }
    }
    for (; isdigit(c); c = getchar()) {
        x = x * 10 + c - '0';
    }
    if (f) {
        x = -x;
    }
}

Vector read_Vector() {
    double x, y;
    scanf("%lf%lf", &x, &y);
    return Vector(x, y);
} 

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

Vector operator + (Vector A, Vector B) {return Vector(A.x + B.x, A.y + B.y);}

Vector operator - (Vector A, Vector B) {return Vector(A.x - B.x, A.y - B.y);}

Vector operator * (Vector A, double B) {return Vector(A.x * B, A.y * B);}

Vector operator / (Vector A, double B) {return Vector(A.x / B, A.y / B);}

bool operator == (const Vector&a, const Vector&b) {return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;}

double Dot(Vector A, Vector B) {return A.x * B.x + A.y * B.y;}

double Length(Vector A) {return sqrt(A.x * A. x + A. y * A.y);}

double Angle(Vector A, Vector B) {return acos(Dot(A, B) / Length(A) / Length(B));}

double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x;}

double GetS(Vector A, Vector B, Vector C) {return Cross(B - A, C - A);}

bool operator < (Point a, Point b) {
    return a.x < b.x || (a.x == b.x && a.y < b.y);
}

int ConvexHull(Point * p, int N, Point * ch) {
    sort(p, p + N);
    int sum = 0;
    for(int i = 0; i < N; i++) {
        while(sum > 1 && dcmp(Cross(ch[sum - 1] - ch[sum - 2], p[i] - ch[sum - 2]) >= 0)) sum--;
        ch[sum++] = p[i];
    }
    int k = sum;
    for(int i = N - 2; i >= 0; i--) {
        while(sum > k && dcmp(Cross(ch[sum - 1] - ch[sum - 2], p[i] - ch[sum - 2])) >= 0) sum--;
        ch[sum++] = p[i];
    }
    if(N > 1) sum--;
    return sum;
}

bool chdb (double a, double b) {
    return fabs(a - b) <= eps;
}

int nxt[MAXN << 1];

bool KmpSearch(double * s, double * p, int sLen, int pLen) {  
    int i = 0;  
    int j = 0;    
    while(i < sLen && j < pLen) {  
        if(!chdb(s[i], p[j])) {
            if(j == 0) i++;			
            j = nxt[j];
        }		  
        while(j < pLen && chdb(s[i], p[j])) i++, j++;
        if (j == pLen) return 1;
    }  
    return 0;      
}  

void GetNext(double * p, int Nxt[], int pLen) {  
    Nxt[0] = -1;
    Nxt[1] = 0;  
    int j = 0, i = 1;
    for(i = 1; i < pLen; i++) {  
        while(j > 0 && !chdb(p[i], p[j])) j = Nxt[j];  
        if(chdb(p[i], p[j])) j++;  
        Nxt[i + 1] = j;
    }
}  

int n, m;
Polygon p1, p2, c1, c2;
int sum1, sum2, cnts, cntt;
double S[MAXN << 2], T[MAXN << 1];

void print(double * s, int len) {
    for(int i = 0; i < len; i++) {
        printf("%.2lf%c", s[i], i == len - 1 ? '\n' : ' ');
    }
}

signed main() {
    read(n), read(m);
    for(int i = 0; i < n; i++) p1[i] = read_Vector();
    for(int i = 0; i < m; i++) p2[i] = read_Vector();
    sum1 = ConvexHull(p1, n, c1);
    sum2 = ConvexHull(p2, m, c2);
    if(sum1 != sum2) {
        puts("NO");
        return 0;
    }
    c1[sum1] = c1[0]; c1[sum1 + 1] = c1[1];
    c2[sum2] = c2[0]; c2[sum2 + 1] = c2[1];
    for(int i = 0; i < sum1; i++) {
        S[cnts++] = Length(c1[i + 1] - c1[i]);
        S[cnts++] = Angle(c1[i + 2] - c1[i + 1], 
                    c1[i + 1] - c1[i]);
    }
    for(int i = 0; i < sum2; i++) {
        T[cntt++] = Length(c2[i + 1] - c2[i]);
        T[cntt++] = Angle(c2[i + 2] - c2[i + 1], 
                    c2[i + 1] - c2[i]);
    }
    for(int i = cnts; i < cnts * 2 - 1; i++) S[i] = S[i - cnts];
    GetNext(T, nxt, cntt);
    if(KmpSearch(S, T, cnts * 2 - 2, cntt - 1)) puts("YES");
    else puts("NO");
    return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_37666409/article/details/81568208