BZOJ-2433: [Noi2011]智能车比赛(最短路)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2433

我们可以YY出必定存在最短路仅由S,T,和公共点之间的直线连边构成,那么就每次对于一个点,求出其到右边所有点之间的可行连边,这个可以维护两个斜率上下界,为了保证精度,使用向量来表示,然后要是S在右边,那就和T交换一下,最后最短路一次即可,O(n^2 + n^2 log n)

代码(计算几何太弱了,调了整整两个小时QaQ):

#include <cstdio>

#include <algorithm>

#include <cstring>

#include <queue>

#include <cmath>

#include <vector>

 

using namespace std ;

 

#define travel( x ) for ( vector < edge > :: iterator p = E[ x ].begin(  ) ; p != E[ x ].end(  ) ; ++ p )

#define rep( i , x ) for ( int i = 0 ; i ++ < x ; )

#define REP( i , l , r ) for ( int i = l ; i <= r ; ++ i )

#define addedge( s , t , d ) E[ s ].push_back( edge( t , d ) )

 

const int maxn = 2010 , maxv = 4010  , inf = 0x7fffffff ;

const double esp = 0.0000000000001 ;

 

inline int cmp( double x , double y ) {

    return y - x > esp ? -1 : ( x - y > esp ) ;

}

 

struct edge {

    int t ; double d ;

    edge( int _t , double _d ) : t( _t ) , d( _d ) {

    }

} ;

vector < edge > E[ maxv ] ;

 

double dist[ maxv ] ;

bool f[ maxv ] ;

int S , T , V = 0 , node[ maxn ][ 2 ] ;

 

struct Cmp {

    bool operator (  ) ( int x , int y ) {

        return dist[ x ] > dist[ y ] ;

    }

} ;

priority_queue < int , vector < int > , Cmp > q ;

 

inline double dijkstra(  ) {

    rep( i , V ) dist[ i ] = inf , f[ i ] = true ;

    dist[ S ] = 0 , q.push( S ) ;

    int now ; double cost ;

    while ( ! q.empty(  ) ) {

        now = q.top(  ) ; q.pop(  ) ;

        if ( ! f[ now ] ) continue ;

        f[ now ] = false ;

        if ( now == T ) return dist[ T ] ;

        travel( now ) if ( cmp( dist[ p -> t ] , cost = dist[ now ] + p -> d ) == 1 ) {

            dist[ p -> t ] = cost , f[ p -> t ] = true , q.push( p -> t ) ;

        }

    }

    return dist[ T ] ;

}

 

struct Point {

    double x , y ;

    void Read(  ) {

        scanf( "%lf%lf" , &x , &y ) ;

    }

} ;

 

struct Vector {

    double x , y ;

    Vector( double _x , double _y ) : x( _x ) , y( _y ) {

    }

} ;

 

Vector operator - ( const Point &a , const Point &b ) {

    return Vector( a.x - b.x , a.y - b.y ) ;

}

 

double operator * ( const Vector &a , const Vector &b ) {

    return a.x * b.y - b.x * a.y ;

}

 

inline double sqr( double val ) {

    return val * val ;

}

 

inline double Dist( const Point &a , const Point &b ) {

    return sqrt( sqr( a.x - b.x ) + sqr( a.y - b.y ) ) ;

}

 

Point st , to , pos[ maxn ][ 2 ] , px[ maxn ][ 2 ] ;

double sp , ans ;

int n , ps = 0 , pt = 0 ;

 

inline void make_edge( Point P , int N , int M ) {

    Vector L = Vector( 0 , 1 ) , R = Vector( 0 , -1 ) ;

    REP( i , N , pt ) {

        if ( cmp( ( px[ i ][ 0 ] - P ) * L , 0 ) != -1 && cmp( R * ( px[ i ][ 0 ] - P ) , 0 ) != -1 ) {

            addedge( M , node[ i ][ 0 ] , Dist( P , px[ i ][ 0 ] ) ) ;

            L = ( px[ i ][ 0 ] - P ) ;

        } else if ( cmp( ( px[ i ][ 0 ] - P ) * R , 0 ) == 1 ) break ;

        if ( cmp( ( px[ i ][ 1 ] - P ) * L , 0 ) != -1 && cmp( R * ( px[ i ][ 1 ] - P ) , 0 ) != -1 ) {

            addedge( M , node[ i ][ 1 ] , Dist( P , px[ i ][ 1 ] ) ) ;

            R = ( px[ i ][ 1 ] - P ) ;

        } else if ( cmp( L * ( px[ i ][ 1 ] - P ) , 0 ) == 1 ) break ;

    }

}

 

int main(  ) {

    scanf( "%d" , &n ) ;

    rep( i , n ) pos[ i ][ 0 ].Read(  ) , pos[ i ][ 1 ].Read(  ) ;

    st.Read(  ) ; to.Read(  ) ; scanf( "%lf" , &sp ) ;

    if ( st.x > to.x ) swap( st , to ) ;

    rep( i , n ) {

        if ( ! ps ) {

            if ( cmp( st.x , pos[ i ][ 0 ].x ) != -1 && cmp( st.x , pos[ i ][ 1 ].x ) != 1 && cmp( st.y , pos[ i ][ 0 ].y ) != -1 && cmp( st.y , pos[ i ][ 1 ].y ) != 1 ) {

                ps = i ;

            }

        }

        if ( ! pt ) {

            if ( cmp( to.x , pos[ i ][ 0 ].x ) != -1 && cmp( to.x , pos[ i ][ 1 ].x ) != 1 && cmp( to.y , pos[ i ][ 0 ].y ) != -1 && cmp( to.y , pos[ i ][ 1 ].y ) != 1 ) {

                pt = i ;

            }

        }

    }

    if ( ps == pt ) ans = Dist( st , to ) ; else {

        REP( i , ps , ( pt - 1 ) ) {

            px[ i ][ 0 ].x = px[ i ][ 1 ].x = pos[ i ][ 1 ].x ;

            px[ i ][ 0 ].y = min( pos[ i ][ 1 ].y , pos[ i + 1 ][ 1 ].y ) ;

            px[ i ][ 1 ].y = max( pos[ i ][ 0 ].y , pos[ i + 1 ][ 0 ].y ) ;

        }

        px[ pt ][ 0 ] = px[ pt ][ 1 ] = to ;

        REP( i , ps , ( pt - 1 ) ) {

            node[ i ][ 0 ] = ++ V , node[ i ][ 1 ] = ++ V ;

        }

        S = ++ V , node[ pt ][ 0 ] = node[ pt ][ 1 ] = T = ++ V ;

        make_edge( st , ps , S ) ;

        REP( i , ps , ( pt - 1 ) ) {

            make_edge( px[ i ][ 0 ] , i , node[ i ][ 0 ] ) , make_edge( px[ i ][ 1 ] , i , node[ i ][ 1 ] ) ;

        }

        ans = dijkstra(  ) ;

    }

    printf( "%.10f\n" , ans / sp ) ;

    return 0 ;

}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容