hdu 3902 Swordsman 判断多边形是否轴对称以及对称轴个数

Problem Description
Mr. AC is a swordsman. His dream is to be the best swordsman in the world. To achieve his goal, he practices every day. There are many ways to practice, but Mr. AC likes “Perfect Cut” very much. The “Perfect Cut” can be described as the following two steps:
1.  Put a piece of wood block on the desk, and then suddenly wave the sword, cutting the block into two pieces.
2.  Without any motion, the two pieces must be absolutely axial symmetry.
According to the step two, when the board is an axial symmetry figure, Mr. AC has a chance to achieve the “Perfect Cut”. Now give you a board, and you should tell if Mr. AC has a chance to complete the “Perfect Cut”. The board is a simple polygon.
 

Input
The input contains several cases. 
The first line of one case contains a single integer n (3 <= n <= 20000), the number of points. The next n lines indicate the points of the simple polygon, each line with two integers x, y (0 <= x, y <= 20000). The points would be given either clockwise or counterclockwise.
 

Output
For each case, output the answer in one line. If Mr. AC has the chance, print “YES”, otherwise "NO".
 

Sample Input
 
   
3 0 0 2 0 0 1 4 0 0 0 1 1 1 1 0
 

Sample Output
 
   
NO YES

//就算对称轴的个数

#include
#include
#include
#include
#include
#include
using namespace std;


const int maxn=20010;
int N,M,Tot,next[maxn];
int x[maxn],y[maxn];
long long ans;


struct Point
{
    long long ed,ag;
}P[2*maxn],Q[maxn];


bool operator==(Point A,Point B)
{
    return A.ed==B.ed&&A.ag==B.ag;
}


void scanInt(int &x)
{
    char ch;
    while(ch=getchar(),ch<'0'||ch>'9');
    x=ch-'0';
    while(ch=getchar(),ch>='0'&&ch<='9')x*=10,x+=ch-'0';
}


void FindNext()
{
    next[0]=-1;
    next[1]=0;
    for(int i=2;i     {
        int p=next[i-1];
        for(;!(Q[p]==Q[i-1])&&p;)
        p=next[p];
        if(Q[p]==Q[i-1])next[i]=p+1;else next[i]=0;
    }



bool CP(long long a,long long b,long long c,long long d)
{
    return a*d-b*c>0;
}


int main()
{
    int Case;
    while (~scanf("%d",&N))
    {
        for(int i=0;i         {
            scanf("%I64d",x+i);
            scanf("%I64d",y+i);
        }
        x[N]=x[0];
        y[N]=y[0];
        x[N+1]=x[1];
        y[N+1]=y[1];
        for(int i=0;i         {
            long long tmp=x[i+1]-x[i];
            tmp*=tmp;
            P[i].ed=tmp;
            tmp=y[i+1]-y[i];
            tmp*=tmp;
            P[i].ed+=tmp;
            tmp=x[i+2]-x[i];
            tmp*=tmp;
            P[i].ag=tmp;
            tmp=y[i+2]-y[i];
            tmp*=tmp;
            P[i].ag+=tmp;
            if(CP(x[i+2]-x[i],y[i+2]-y[i],x[i+1]-x[i],y[i+1]-y[i]))P[i].ag=-P[i].ag;
        }
        for(int i=2;i<=N;++i)
        {
            long long tmp=x[i]-x[i-1];
            tmp*=tmp;
            Q[N-i].ed=tmp;
            tmp=y[i]-y[i-1];
            tmp*=tmp;
            Q[N-i].ed+=tmp;
            tmp=x[i]-x[i-2];
            tmp*=tmp;
            Q[N-i].ag=tmp;
            tmp=y[i]-y[i-2];
            tmp*=tmp;
            Q[N-i].ag+=tmp;
            if(!CP(x[i-2]-x[i],y[i-2]-y[i],x[i-1]-x[i],y[i-1]-y[i]))Q[N-i].ag=-Q[N-i].ag;
        }
        long long tmp=x[1]-x[0];
        tmp*=tmp;
        Q[N-1].ed=tmp;
        tmp=y[1]-y[0];
        tmp*=tmp;
        Q[N-1].ed+=tmp;
        tmp=x[1]-x[N-1];
        tmp*=tmp;
        Q[N-1].ag=tmp;
        tmp=y[1]-y[N-1];
        tmp*=tmp;
        Q[N-1].ag+=tmp;
        if(!CP(x[N-1]-x[1],y[N-1]-y[1],x[0]-x[1],y[0]-y[1]))Q[N-1].ag=-Q[N-1].ag;
        memcpy(P+N,P,N*sizeof(Point));


        int p=0;
        ans=0;
        FindNext();
        for(int i=0;i<(N<<1)-1;++i)
        {
            for(;!(P[i]==Q[p])&&p;)p=next[p];
            if(P[i]==Q[p])
            {
                if(p==N-1)
                {
                    ans++;//ans记录对称轴的个数 
                    p=next[p];
                    if(P[i]==Q[p])p++;
                    continue;
                }
                p++;
            }
        }
        if(ans)printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}


//n^2

#include
#include
using namespace std;


//
struct XY;


inline double crsProd(const XY&, const XY&);
inline double dotProd(const XY&, const XY&);


//A 2-dimensional point or vector.
struct XY {
    double x;
    double y;


    void set(double _x, double _y) {
        x = _x;
        y = _y;
    }


    XY operator - (const XY& other) const {
        XY result = {x - other.x, y - other.y};
        return result;
    }


    XY operator + (const XY& other) const {
        XY result = {x + other.x, y + other.y};
        return result;
    }


    XY operator / (double d) const {
        XY result = {x / d, y / d};
        return result;
    }


    //Square of the length of this vector. Sometimes you just want to compare
    //the lengths of two vectors, so you needn't calculate the square roots.
    double normSqr() const {
        return x * x + y * y;
    }
};


//Cross product of vector a and b
inline double crsProd(const XY& a, const XY& b) {
    return a.x * b.y - b.x * a.y;
}


//Dot product of vector a and b
inline double dotProd(const XY& a, const XY& b) {
    return a.x * b.x + a.y * b.y;
}


//Whether point a and b are symmetric about line (axis1, axis2).
bool isSymm(const XY& a, const XY& b, const XY& axis1, const XY& axis2) {
    return dotProd(a - b, axis1 - axis2) == 0.0
           && (a - axis1).normSqr() == (b - axis1).normSqr();
}
//





const int MAX_POINT = 21100;


XY g_point[MAX_POINT];
int g_pntCnt;


bool solveEven() {
    bool symm = false;
    int halfCnt = g_pntCnt / 2;
    for (int i = 0; i < halfCnt && !symm; i++) {
        symm = true;
        XY axis1 = g_point[i];
        XY axis2 = g_point[(i + halfCnt ) % g_pntCnt];
        for (int j = 1; j < halfCnt && symm; j++) {
            XY left = g_point[(i + j) % g_pntCnt];
            XY right = g_point[(i + g_pntCnt - j) % g_pntCnt];
            if (!isSymm(left, right, axis1, axis2)) {
                symm = false;
            }
        }
        if (!symm) {
            symm = true;
            XY axis1 = (g_point[i] + g_point[(i + 1) % g_pntCnt]) / 2.0;
            XY axis2 = (g_point[(i + halfCnt) % g_pntCnt]
                        + g_point[(i + halfCnt + 1) % g_pntCnt]
                       ) / 2.0;
            for (int j = 1; j < halfCnt && symm; j++) {
                XY left = g_point[(i + j) % g_pntCnt];
                XY right = g_point[(i + g_pntCnt - j + 1) % g_pntCnt];
                if (!isSymm(left, right, axis1, axis2)) {
                    symm = false;
                }
            }
        }
    }
    return symm;
}


bool solveOdd() {
    bool symm = false;
    int halfCnt = g_pntCnt / 2;
    for (int i = 0; i < g_pntCnt && !symm; i++) {
        symm = true;
        XY axis1 = g_point[i];
        XY axis2 = (g_point[(i + halfCnt) % g_pntCnt]
                    + g_point[(i + halfCnt + 1) % g_pntCnt]
                   ) / 2.0;
        for (int j = 1; j <= halfCnt && symm; j++) {
            XY left = g_point[(i + j) % g_pntCnt];
            XY right = g_point[(i + g_pntCnt - j) % g_pntCnt];
            if (!isSymm(left, right, axis1, axis2)) {
                symm = false;
            }
        }
    }
    return symm;
}


void solve() {
    bool symm;
    if (g_pntCnt % 2 == 0) {
        symm = solveEven();
    }
    else {
        symm = solveOdd();
    }
    if (symm) {
        printf("YES\n");
    }
    else {
        printf("NO\n");
    }
}






int main() {
    while(scanf("%d",&g_pntCnt)==1)
    {
        for (int i = 0; i < g_pntCnt; i++) {
            scanf("%lf%lf",&g_point[i].x ,& g_point[i].y);
        }
        solve();
    }
    return 0;
}

//nlog(n)

#include
#include
#include
#include
#include
#include
using namespace std;


#define N 80100
//#define swap( a, b ) ( a ^= b ^= a ^= b )


#define eps 1e-8


//---------------------------------------------------------------------------------------------
clock_t st, end;


struct point {
double x, y;
point ( void ) {}
point ( double x0, double y0 ) { x = x0; y = y0; }
point ( const point& m ) { x = m.x; y = m.y; }
} P[ N ];


double operator ^ ( const point& a, const point& b ) {
return a.x * b.y - a.y * b.x;
}


double operator * ( const point& a, const point& b ) {
return a.x * b.x + a.y * b.y;
}


point operator - ( const point& a, const point& b ) {
return point ( a.x - b.x, a.y - b.y );
}


double disf ( const point& a, const point& b ) {
return ( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y );
}


double turn ( const point& a, const point& b, const point& c ) {
point A ( b - a ), B ( c - b );
if ( ( A ^ B ) > 0 ) return ( A * B / sqrt ( ( A * A ) * ( B * B ) ) );
else return ( A * B / sqrt ( ( A * A ) * ( B * B ) ) ) - 2;
}


struct Data {
int I, L, R;
double L0, R0;
} data[ N ];


bool cmp1 ( const Data& a, const Data& b ) { return a.L0 < b.L0; }
bool cmp2 ( const Data& a, const Data& b ) { return a.R0 < b.R0; }
bool cmp3 ( const Data& a, const Data& b ) { return a.I  < b.I ; }


//---------------------------------------------------------------------------------------------


int sa1[ N ],rank1[ N ],height1[ N ];
int sa2[ N ],rank2[ N ],height2[ N ];


int bs[ N ],t1[ N ],t2[ N ],cur[ N ],r[ N ];


void suffix_array ( int* sa, int* rank, int len, int m ) {
int i, j, p;
int *temp1 = t1, *temp2 = t2, *t;
memset ( bs, 0, sizeof ( bs ) );
for ( i = 0 ; i < len ; ++i ) ++bs[ temp1[ i ] = r[ i ] ];
for ( i = 1 ; i < m ; ++i ) bs[ i ] += bs[ i - 1 ];
for ( i = len - 1 ; i >= 0 ; --i ) sa[ --bs[ r[ i ] ] ] = i;


for ( j = p = 1 ; p < len ; j *= 2, m = p ) {
for ( p = 0, i = len - j ; i < len ; ++i ) temp2[ p++ ] = i;
for ( i = 0 ; i < len ; ++i ) if ( sa[ i ] >= j ) temp2[ p++ ] = sa[ i ] - j;
for ( i = 0 ; i < len ; ++i ) cur[ i ] = temp1[ temp2[ i ] ];
memset ( bs, 0, sizeof ( bs ) );
for ( i = 0 ; i < len ; ++i ) ++bs[ cur[ i ] ];
for ( i = 1 ; i < m ; ++i ) bs[ i ] += bs[ i - 1 ];
for ( i = len - 1 ; i >= 0 ; --i ) sa[ --bs[ cur[ i ] ] ] = temp2[ i ];
for ( temp2[ sa[ 0 ] ] = 0, i = p = 1 ; i < len ; ++i ) {
if ( temp1[ sa[ i - 1 ] ] == temp1[ sa[ i ] ] &&
temp1[ sa[ i - 1 ] + j ] == temp1[ sa[ i ] + j ] ) {
temp2[ sa[ i ] ] = p - 1;
}
else temp2[ sa[ i ] ] = p++;
}
t = temp1; temp1 = temp2; temp2 = t;
}
}


void calheight ( int* height, int* sa, int* rank, int len ) {
int i, j;
for ( i = 1 ; i < len ; ++i ) {//由于排第一的一定是最后的0 所以不用算它
rank[ sa[ i ] ] = i;
}
for ( i = j = 0 ; i < len - 1 ; ++i ) {
if ( j ) --j;
// 如果sa[rank[i]]与sa[rank[i]-1]前j个字符匹配(j!=0) 那么rank[i+1]与那个字串至少有j-1个是一样的
while ( r[ i + j ] == r[ sa[ rank[ i ] - 1 ] + j ] ) ++j;
height[ rank[ i ] ] = j;
}
}


//---------------------------------------------------------------------------------------------


int st1[ 20 ][ N ], st2[ 20 ][ N ];
int ln[ N ];


void initrmq ( int n ) {
int i, j, k, sk;
ln[ 0 ] = ln[ 1 ] = 0;
for ( i = 0 ; i < n ; i++ ) st1[ 0 ][ i ] = height1[ i ];
for ( i = 0 ; i < n ; i++ ) st2[ 0 ][ i ] = height2[ i ];
for ( i = 1, k = 2 ; k < n ; i++, k <<= 1 ) {
for ( j = 0, sk = ( k >> 1 ) ; j < n ; ++j, ++sk ) {
st1[ i ][ j ] = st1[ i - 1 ][ j ];
st2[ i ][ j ] = st2[ i - 1 ][ j ];
if ( sk < n && st1[ i ][ j ] > st1[ i - 1 ][ sk ] )
st1[ i ][ j ] = st1[ i - 1 ][ sk ];
if ( sk < n && st2[ i ][ j ] > st2[ i - 1 ][ sk ] )
st2[ i ][ j ] = st2[ i - 1 ][ sk ];
}
for ( j = ( k >> 1 ) + 1 ; j <= k ; ++j ) ln[ j ] = ln[ k >> 1 ] + 1;
}
for ( j = ( k >> 1 ) + 1 ; j <= n ; ++j ) ln[ j ] = ln[ k >> 1 ] + 1;
}


int query1 ( int x, int y ) { // min of { val[x] ... val[y] }
int bl = ln[ y - x + 1 ];
return min ( st1[ bl ][ x ], st1[ bl ][ y - ( 1 << bl ) + 1 ] );
}


int query2 ( int x, int y ) {
int bl = ln[ y - x + 1 ];
return min ( st2[ bl ][ x ], st2[ bl ][ y - ( 1 << bl ) + 1 ] );
}


//---------------------------------------------------------------------------------------------


bool solve ( int n ) {
for ( int i = 0 ; i < n ; ++i ) {
scanf ( "%lf%lf", &P[ i ].x, &P[ i ].y );
}
for ( int now = 0 ; now < n ; ++now ) {
int pre = ( now - 1 + n ) % n;
int nxt = ( now + 1 ) % n;
data[ now ].I = now;
data[ now ].L0 = disf ( P[ now ], P[ nxt ] );
data[ now ].R0 = turn ( P[ pre ], P[ now ], P[ nxt ] );
}
sort ( data, data + n, cmp1 );
data[ 0 ].L = 0;
for ( int now = 1, m = 0 ; now < n ; ++now ) {
if ( fabs( data[ now - 1 ].L0 - data[ now ].L0 ) < eps ) data[ now ].L = m;
else data[ now ].L = ++m;
}
sort ( data, data + n, cmp2 );
data[ 0 ].R = 0;
for ( int now = 1, m = 0 ; now < n ; ++now ) {
if ( fabs( data[ now - 1 ].R0 - data[ now ].R0 ) < eps ) data[ now ].R = m;
else data[ now ].R = ++m;
}
sort ( data, data + n, cmp3 );
for ( int i = 0 ; i < n ; ++i ) {
r[ 4 * n - i ] = r[ 4 * n - i - n ] =
r[ i ] = r[ i + n ] = data[ i ].L + 2;
}
r[ n + n ] = 1;
r[ 4 * n + 1 ] = 0;
suffix_array ( sa1, rank1, 4 * n + 2, 4 * n + 4 );
calheight( height1, sa1, rank1, 4 * n + 2 );


for ( int i = 0 ; i < n ; ++i ) {
r[ 4 * n - i ] = r[ 4 * n - i - n ] =
r[ i ] = r[ i + n ] = data[ i ].R + 2;
}
r[ n + n ] = 1;
r[ 4 * n + 1 ] = 0;
suffix_array ( sa2, rank2, 4 * n + 2, 4 * n + 4 );
calheight( height2, sa2, rank2, 4 * n + 2 );


initrmq ( 4 * n + 2 );
int a, b;
for ( int i = 0 ; i < n ; ++i ) {
a = rank1[ ( i + 1 ) % n ], b = rank1[ 4 * n - ( i - 1 + n ) ];
if ( a > b ) swap ( a, b );
int cmp1 = query1 ( a + 1, b );
a = rank2[ ( i + 1 ) % n ], b = rank2[ 4 * n - ( i + n ) ];
if ( a > b ) swap ( a, b );
int cmp2 = query2 ( a + 1, b );


//if ( cmp1 >= n && cmp2 >= n ) return true;
if ( cmp1 >= n - 1 && cmp2 >= n ) return true;
}
// 角
for ( int i = 0 ; i < n ; ++i ) {
a = rank2[ ( i + 1 ) % n ], b = rank2[ 4 * n - ( i - 1 + n ) ];
if ( a > b ) swap ( a, b );
int cmp2 = query2 ( a + 1, b );
a = rank1[ i ], b = rank1[ 4 * n - ( i - 1 + n ) ];
if ( a > b ) swap ( a, b );
int cmp1 = query1 ( a + 1, b );


//if ( cmp2 >= n && cmp1 >= n ) return true;
if ( cmp2 >= n - 1 && cmp1 >= n ) return true;
}
return false;
}


int main ( void ) {
//freopen ( "data.in", "r", stdin );
//freopen ( "data.out", "w", stdout );
int n;
while ( scanf ( "%d", &n ) != EOF ) {
if ( solve ( n ) ) puts ( "YES" );
else puts ( "NO" );
}
// cerr << clock( ) << endl;
return 0;
}


你可能感兴趣的:(acm_数学问题)