您的位置:首页 > 其它

【POJ】1556 The Doors 最短路+判断线段相交

2014-09-03 20:36 288 查看
传送门:【POJ】1556 The Doors

题目分析:状态太差了。。这题花了好久才写出来。。

题目倒是很简单,直接枚举边的起点u,终点v,看是否能够沿着直线从u走到v,如果可以则建边u-v,最后最短路即可。并且因为本题是DAG图,所以可以DP。

代码如下:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

#define REP( i , a , b ) for ( int i = ( a ) ; i <  ( b ) ; ++ i )
#define FOR( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )
#define REV( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
#define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next )
#define CLR( a , x ) memset ( a , x , sizeof a )

const int MAXN = 1000 ;
const int MAXE = 100000 ;
const double eps = 1e-6 ;
const double INF = 1e10 ;

struct Point {
	double x , y ;
	Point () {}
	Point ( double x , double y ) : x ( x ) , y ( y ) {}
	Point operator - ( const Point& p ) const {
		return Point ( x - p.x , y - p.y ) ;
	}
} p[MAXN] ;

struct Edge {
	int v ;
	double c ;
	Edge* next ;
} E[MAXE] , *H[MAXN] , *cur ;

int n ;
int Q[MAXN] , head , tail ;
int in[MAXN] ;
double d[MAXN] ;

void clear () {
	cur = E ;
	CLR ( in , 0 ) ;
	CLR ( H , 0 ) ;
}

void addedge ( int u , int v , double c ) {
	cur -> v = v ;
	cur -> c = c ;
	cur -> next = H[u] ;
	H[u] = cur ++ ;
}

double Cross ( const Point& a , const Point& b ) {
	return a.x * b.y - a.y * b.x ;
}

double dist ( Point a ) {
	return sqrt ( a.x * a.x + a.y * a.y ) ;
}

bool Intersect ( Point a1 , Point a2 , Point b1 , Point b2 ) {
	if ( Cross ( a1 - a2 , b1 - a2 ) * Cross ( a1 - a2 , b2 - a2 ) <= eps )	return 1 ;
	return 0 ;
}	

bool check ( Point a1 , Point a2 , int low , int high ) {
	REP ( i , low , high )
		if ( !Intersect ( a1 , a2 , p[i * 4 + 1] , p[i * 4 + 2] )
		&&   !Intersect ( a1 , a2 , p[i * 4 + 3] , p[i * 4 + 4] ) ) return 0 ;
	return 1 ;
}

void topo () {
	FOR ( i , 1 , n * 4 + 1 ) d[i] = INF ;
	head = tail = 0 ;
	FOR ( i , 0 , n * 4 + 1 ) if ( !in[i] ) Q[tail ++] = i ;
	d[0] = 0 ;
	while ( head != tail ) {
		int u = Q[head ++] ;
		travel ( e , H , u ) {
			int v = e -> v ;
			if ( -- in[v] == 0 ) Q[tail ++] = v ;
			if ( d[v] > d[u] + e -> c ) d[v] = d[u] + e -> c ;
		}
	}
}
	

void solve () {
	double x ;
	clear () ;
	p[0].x = 0 ;
	p[0].y = 5 ;
	p[n * 4 + 1].x = 10 ;
	p[n * 4 + 1].y = 5 ;
	REP ( i , 0 , n ) {
		scanf ( "%lf" , &x ) ;
		REP ( j , 1 , 5 ) {
			scanf ( "%lf" , &p[i * 4 + j].y ) ;
			p[i * 4 + j].x = x ;
		}
	}
	if ( check ( p[0] , p[n * 4 + 1] , 0 , n ) ) {
		printf ( "10.00\n" ) ;
		return ;
	}
	REP ( i , 0 , n ) {
		REP ( j , 1 , 5 ) {
			if ( check ( p[0] , p[i * 4 + j] , 0 , i ) ) {
				addedge ( 0 , i * 4 + j , dist ( p[0] - p[i * 4 + j] ) ) ;
				in[i * 4 + j] ++ ;
			}
			if ( check ( p[n * 4 + 1] , p[i * 4 + j] , i + 1 , n ) ) {
				addedge ( i * 4 + j , n * 4 + 1 , dist ( p[n * 4 + 1] - p[i * 4 + j] ) ) ;
				in[n * 4 + 1] ++ ;
			}
			REP ( k , i + 1 , n )
				REP ( l , 1 , 5 )
					if ( check ( p[i * 4 + j] , p[k * 4 + l] , i + 1 , k ) ) {
						addedge ( i * 4 + j , k * 4 + l , dist ( p[i * 4 + j] - p[k * 4 + l] ) ) ;
						in[k * 4 + l] ++ ;
					}
		}
	}
	topo () ;
	printf ( "%.2f\n" , d[n * 4 + 1] ) ;
}

int main () {
	while ( ~scanf ( "%d" , &n ) && ~n ) solve () ;
	return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: