1556

来源:互联网 发布:一手淘宝买家数据 编辑:程序博客网 时间:2024/06/05 05:14
 
#include <cstdio>#include <cmath>#include <string>#include <vector>using namespace std;struct point{double x, y;};struct edge{int vertex;double dist;edge *next;};class priority_queue4dijkstra{public:struct element{int vertex;double dist;};public:priority_queue4dijkstra(const int cap){queue.resize(cap + 1);pos.assign(cap + 1, 0);num = 0;}void reset(){num = 0;}bool empty(){return 0 == num;}int top(){return queue[1].vertex;}void insert(const element &x){++num;int tmp = num;for(int parent = tmp / 2; parent >= 1 && x.dist < queue[parent].dist; tmp = parent, parent /= 2){pos[queue[parent].vertex] = tmp;queue[tmp] = queue[parent];}pos[x.vertex] = tmp;queue[tmp] = x;}void erase(const int vertex){if(0 == pos[vertex]){return;}int hole = pos[vertex];pos[vertex] = 0;const element &tmp = queue[num];--num;for(int child = hole * 2; child <= num; hole = child, child *= 2){if(child + 1 <= num && queue[child + 1].dist < queue[child].dist){++child;}if(queue[child].dist < tmp.dist){pos[queue[child].vertex] = hole;queue[hole] = queue[child];}else{break;}}pos[tmp.vertex] = hole;queue[hole] = tmp;}private:vector<element> queue;vector<int> pos;int num;};const double MIN = 1e-8;int num, v;double x[20];double y[20][4];double dist[100];edge *g[100];edge mem[10000];int index;priority_queue4dijkstra q(100);bool input(){scanf("%d", &num);if(-1 == num){return false;}for(int i = 1; i <= num; ++i){scanf("%lf%lf%lf%lf%lf", &x[i], &y[i][0], &y[i][1], &y[i][2], &y[i][3]);}return true;}inline double cal_dist(const point &p1, const point &p2){const double x = p1.x - p2.x, y = p1.y - p2.y;return sqrt(x * x + y * y);}inline double multi(const double x1, const double y1, const double x2, const double y2){return x1 * y2 - x2 * y1;}inline int cross(const point &l1, const point &l2, const point &p){const double product = multi(l1.x - l2.x, l1.y - l2.y, p.x - l2.x, p.y - l2.y);if(abs(product) < MIN){return 0;}return (product < 0)? -1: 1;}double can_move_straight2a_point(const int left_wall, const point &left_point, const int right_wall, const point &right_point){point segment1, segment2, segment3, segment4;for(int i = left_wall + 1; i < right_wall; ++i){segment1.x = x[i];segment1.y = y[i][0];segment2.x = x[i];segment2.y = y[i][1];segment3.x = x[i];segment3.y = y[i][2];segment4.x = x[i];segment4.y = y[i][3];if(cross(left_point, right_point, segment1) * cross(left_point, right_point, segment2) > 0&& cross(left_point, right_point, segment3) * cross(left_point, right_point, segment4) > 0){return -1.0;}}return cal_dist(left_point, right_point);}void build(){v = 2;const int total_vertex = num * 4 + 2;memset(g, NULL, sizeof(edge *) * (total_vertex + 1));point left_point, right_point;index = 0;for(int i = 1; i <= num; ++i){for(int j = 0; j < 4; ++j){++v;right_point.x = x[i];right_point.y = y[i][j];left_point.x = 0.0;left_point.y = 5.0;const double outcome = can_move_straight2a_point(0, left_point, i, right_point);if(outcome >= MIN){edge *tmp = &mem[index];++index;tmp ->next = g[1];g[1] = tmp;tmp ->vertex = v;tmp ->dist = outcome;}int left_vertex = 2;for(int a = 1; a < i; ++a){for(int b = 0; b < 4; ++b){left_point.x = x[a];left_point.y = y[a][b];++left_vertex;const double outcome1 = can_move_straight2a_point(a, left_point, i, right_point);if(outcome1 > MIN){edge *tmp = &mem[index];++index;tmp ->next = g[left_vertex];g[left_vertex] = tmp;tmp ->vertex = v;tmp ->dist = outcome1;}}}left_point = right_point;right_point.x = 10.0;right_point.y = 5.0;const double outcome2 = can_move_straight2a_point(i, left_point, num + 1, right_point);if(outcome2 > MIN){edge *tmp = &mem[index];++index;tmp ->next = g[v];g[v] = tmp;tmp ->vertex = 2;tmp ->dist = outcome2;}}}left_point.x = 0.0;left_point.y = 5.0;right_point.x = 10.0;right_point.y = 5.0;const double outcome3 = can_move_straight2a_point(0, left_point, num + 1, right_point);if(outcome3 > MIN){edge *tmp = &mem[index];++index;tmp ->next = g[1];g[1] = tmp;tmp ->vertex = 2;tmp ->dist = outcome3;}}void dijkstra(){bool finished[100] = {false};finished[1] = true;dist[1] = 0.0;for(int i = 2; i <= v; ++i){dist[i] = 1e12;}priority_queue4dijkstra::element tmp_node;q.reset();for(edge *p = g[1]; p; p = p ->next){dist[p ->vertex] = p ->dist;tmp_node.vertex = p ->vertex;tmp_node.dist = p ->dist;q.insert(tmp_node);}for(int i = 2; i <= v; ++i){const int u = q.top();if(2 == u){return;}q.erase(u);finished[u] = true;for(edge *p = g[u]; p; p = p ->next){if(!finished[p ->vertex] && dist[u] + p ->dist < dist[p ->vertex]){q.erase(p ->vertex);dist[p ->vertex] = dist[u] + p ->dist;tmp_node.vertex = p ->vertex;tmp_node.dist = dist[p ->vertex];q.insert(tmp_node);}}}}int main(){while(input()){build();dijkstra();printf("%.2f\n", dist[2]);}return 0;}

原创粉丝点击