zoukankan      html  css  js  c++  java
  • poj 2187 Beauty Contest(凸包+旋转卡壳)

    通过这题有学习了关于求凸多边形的直径的方法,真的很巧妙~

    旋转卡壳可以用于求凸包的直径、宽度,两个不相交凸包间的最大距离和最小距离等,参考了下面的两个博客,原理基本上明白了。留下链接,以便后面复习用~

    http://www.cnblogs.com/Booble/archive/2011/04/03/2004865.html

    http://www.cppblog.com/staryjy/archive/2009/11/19/101412.html

    其实这题完全可以不用旋转卡壳,可能是后台数据量很小,直接用暴力求解也可以过,而且时间和用了旋转卡壳的时间相差无几。

    不用旋转卡壳(125ms)

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <math.h>
    #include <string>
    #define N 50005
    using namespace std ;
    
    struct node
    {
        int x ;
        int y ;
    }p[N] , q[N] ;
    
    int n , top ;
    
    int dis ( struct node a , struct node b )
    {
        return (( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ));
    }
    
    double cross ( struct node p1 , struct node p2 , struct node p0 )
    {
        return (( p1.x -p0.x ) * ( p2.y - p0.y ) - ( p2.x - p0.x ) * ( p1.y - p0.y ));
    }
    
    int cmp ( struct node p1 , struct node p2 )
    {
        if ( cross ( p1 , p2 , p[0] ) > 0 )
        return 1 ;
        if ( cross ( p1 , p2 , p[0] ) == 0 && dis( p1 , p[0] ) < dis( p2 , p[0] ))
        return 1 ;
        return 0 ;
    }
    
    void Graham ()
    {
        int i , j , k ;
        k = 0 ;
        for ( i = 1 ; i < n ; i++ )
        if ( (p[i].y < p[k].y ) || ( p[i].y == p[k].y && p[i].x < p[k].x ))
        k = i ;
    
        struct node tem = p[k] ;
        p[k] = p[0] ;
        p[0] = tem ;
    
        sort ( p , p + n , cmp );
    
        top = 0 ;
        q[top++] = p[0] ;
        q[top++] = p[1] ;
        q[top++] = p[2] ;
        for ( i = 3 ; i < n ; i++ )
        {
            while ( cross ( p[i] , q[top-1] , q[top-2] ) >= 0 )
            top-- ;
            q[top++] = p[i] ;
        }
    }
    
    int main()
    {
        int i , j ;
    
        scanf ( "%d" , &n ) ;
        for ( i = 0 ; i < n ; i++ )
        scanf ( "%d%d" , &p[i].x , &p[i].y );
        if ( n == 2 )
        {
            printf ( "%d\n" , ((p[0].x - p[1].x ) * ( p[0].x - p[1].x )) + ( p[0].y - p[1].y ) * ( p[0].y - p[1].y )) ;
            return 0 ;
        }
        Graham();
        int maxx = 0 ;
        if ( top < 0 )
        {
            maxx = dis ( p[0] , p[n-1] );
        }
        else
        for ( i = 0 ; i < top ; i++ )
        {
            for ( j = i + 1 ; j < top ; j++ )
            {
                int len = dis( q[i] ,q[j] );
                if ( len > maxx )
                maxx = len ;
            }
        }
        printf ( "%d\n" , maxx );
        return 0 ;
    }

    用旋转卡壳(110ms)

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <string>
    #define N 50005
    using namespace std ;
    
    struct node
    {
        int x ;
        int y ;
    }p[N] , q[N] ;
    
    int n , top ;
    
    int dis ( struct node p1 , struct node p2 )
    {
        return ( ( p1.x - p2.x ) * ( p1.x - p2.x ) + ( p1.y - p2.y ) * ( p1.y - p2.y ));
    }
    
    int cross ( struct node p1 , struct node p2 , struct node p0 )
    {
        return ( ( p1.x - p0.x ) * ( p2.y - p0.y ) - ( p2.x - p0.x ) * ( p1.y - p0.y ));
    }
    
    int cmp ( struct node p1 , struct node p2 )
    {
        if ( cross( p1 , p2 , p[0] ) > 0 )
        return 1 ;
        if ( cross ( p1 , p2 , p[0] ) == 0 && dis( p1, p[0] ) < dis( p2 , p[0] ))
        return 1 ;
        return 0 ;
    }
    
    void Graham ()
    {
        int i , j , k ;
        k = 0 ;
        for ( i = 1 ; i < n ; i++ )
        if ( ( p[i].y < p[k].y ) || ( p[i].y == p[k].y && p[i].x < p[k].x ))
        k = i;
    
        struct node tem = p[k] ;
        p[k] = p[0] ;
        p[0] = tem ;
    
        sort ( p , p + n , cmp );
    
        top = 0 ;
        q[top++] = p[0] ;
        q[top++] = p[1] ;
        q[top++] = p[2] ;
        for ( i = 3 ; i < n ; i++ )
        {
            while ( cross ( p[i] , q[top-1] , q[top-2] ) >= 0 )
            top-- ;
            q[top++] = p[i] ;
        }
    }
    
    int max (int a , int b)
    {
        return a > b ? a : b ;
    }
    
    int rotating_calipers()
    {
        int j = 1 , ans = 0 ;
        q[top] = q[0] ;
        for(int i = 0 ; i < top ; i++ )
        {
            while(cross( q[i+1] , q[j+1] , q[i] ) > cross( q[i+1] , q[j] , q[i] ))
            j = ( j + 1 ) % top ;
            ans = max( ans , max( dis( q[i] , q[j] ) , dis( q[i+1] , q[j+1] )));
        }
        return ans;
    }
    
    int main()
    {
        int i , d ;
        scanf ( "%d" , &n ) ;
        for ( i = 0 ; i < n ; i++ )
        scanf ( "%d%d" , &p[i].x , &p[i].y );
        if ( n == 2 )
        {
            d = dis ( p[0] , p[1] );
            printf ( "%d\n" , d );
            return 0 ;
        }
        Graham();
        if ( top < 0 )
        {
            d = dis ( p[0] , p[n-1] );
        }
        else
        {
            d = rotating_calipers();
        }
        printf ( "%d\n" , d );
        return 0 ;
    }

     

  • 相关阅读:
    moco-globalsettings
    moco-简述
    stub和mock
    软件测试工作经验分享
    类、对象、方法、属性和实例变量
    你真的对 parseInt有足够的了解吗?
    PhoneGap开发环境搭建(记录一下,仅仅针对Android)
    360 前端面试题
    前端WEB开发工程师面试题-基础部分
    有意思的For循环
  • 原文地址:https://www.cnblogs.com/misty1/p/2597461.html
Copyright © 2011-2022 走看看