POJ (线段相交 最短路) The Doors

题意:

一个正方形中有n道竖直的墙,每道墙上开两个门。求从左边中点走到右边中点的最短距离。

分析:

以起点终点和每个门的两个端点建图,如果两个点可以直接相连(即不会被墙挡住),则权值为两点间的欧几里得距离。

然后求起点到终点的最短路即可。

  1 #include <cstdio>
  2 #include <cmath>
  3 #include <cstring>
  4 #include <vector>
  5 #include <algorithm>
  6 using namespace std;
  7
  8 const int maxn = 50;
  9 const double INF = 1e4;
 10 const double eps = 1e-8;
 11
 12 struct Point
 13 {
 14     double x, y;
 15     Point(double x=0, double y=0):x(x), y(y) {}
 16 }p[maxn * 4];
 17
 18 typedef Point Vector;
 19
 20 Point read_point()
 21 {
 22     double x, y;
 23     scanf("%lf%lf", &x, &y);
 24     return Point(x, y);
 25 }
 26
 27 Point operator - (const Point& A, const Point& B)
 28 { return Point(A.x-B.x, A.y-B.y); }
 29
 30 Vector operator / (const Vector& A, double p)
 31 { return Vector(A.x/p, A.y/p); }
 32
 33 double Dot(const Vector& A, const Vector& B)
 34 { return A.x*B.x + A.y*B.y; }
 35
 36 double Length(const Vector& A)
 37 { return sqrt(Dot(A, A)); }
 38
 39 struct Door
 40 {
 41     double x, y1, y2, y3, y4;
 42     Door(double x=0, double y1=0, double y2=0, double y3=0, double y4=0):x(x), y1(y1), y2(y2), y3(y3), y4(y4) {}
 43 };
 44
 45 vector<Door> door;
 46
 47 double d[maxn * 4], w[maxn * 4][maxn * 4];
 48 bool vis[maxn * 4];
 49 int cnt;
 50
 51 bool isOK(int a, int b)
 52 {//判断两点是否能直接到达
 53     if(p[a].x >= p[b].x) swap(a, b);
 54     for(int i = 0; i < door.size(); ++i)
 55     {
 56         if(door[i].x <= p[a].x) continue;
 57         if(door[i].x >= p[b].x) break;
 58         double k = (p[b].y-p[a].y) / (p[b].x-p[a].x);
 59         double y = p[a].y + k * (door[i].x - p[a].x);
 60         if(!(y>=door[i].y1&&y<=door[i].y2 || y>=door[i].y3&&y<=door[i].y4)) return false;
 61     }
 62     return true;
 63 }
 64
 65 void Init()
 66 {
 67     for(int i = 0; i < cnt; ++i)
 68         for(int j = i; j < cnt; ++j)
 69             if(i == j) w[i][j] = 0;
 70             else w[i][j] = w[j][i] = INF;
 71 }
 72
 73 int main()
 74 {
 75     //freopen("in.txt", "r", stdin);
 76
 77     int n;
 78     while(scanf("%d", &n) == 1 && n + 1)
 79     {
 80         door.clear();
 81         memset(vis, false, sizeof(vis));
 82         memset(d, 0, sizeof(d));
 83
 84         p[0] = Point(0, 5);
 85         cnt = 1;
 86         for(int i = 0; i < n; ++i)
 87         {
 88             double x, y[4];
 89             scanf("%lf", &x);
 90             for(int j = 0; j < 4; ++j) { scanf("%lf", &y[j]); p[cnt++] = Point(x, y[j]); }
 91             door.push_back(Door(x, y[0], y[1], y[2], y[3]));
 92         }
 93         p[cnt++] = Point(10, 5);
 94
 95         Init();
 96
 97         for(int i = 0; i < cnt; ++i)
 98             for(int j = i+1; j < cnt; ++j)
 99             {
100                 double l = Length(Vector(p[i]-p[j]));
101                 if(p[i].x == p[j].x) continue;
102                 if(isOK(i, j))
103                     w[i][j] = w[j][i] = l;
104             }
105         //Dijkstra
106         d[0] = 0;
107         for(int i = 1; i < cnt; ++i) d[i] = INF;
108         for(int i = 0; i < cnt; ++i)
109         {
110             int x;
111             double m = INF;
112             for(int y = 0; y < cnt; ++y) if(!vis[y] && d[y] <= m) m = d[x=y];
113             vis[x] = 1;
114             for(int y = 0; y < cnt; ++y) d[y] = min(d[y], d[x] + w[x][y]);
115         }
116
117         printf("%.2f\n", d[cnt-1]);
118     }
119
120     return 0;
121 }

代码君

时间: 2024-10-07 22:45:53

POJ (线段相交 最短路) The Doors的相关文章

简单几何(线段相交+最短路) POJ 1556 The Doors

题目传送门 题意:从(0, 5)走到(10, 5),中间有一些门,走的路是直线,问最短的距离 分析:关键是建图,可以保存所有的点,两点连通的条件是线段和中间的线段都不相交,建立有向图,然后用Dijkstra跑最短路.好题! /************************************************ * Author :Running_Time * Created Time :2015/10/24 星期六 09:48:49 * File Name :POJ_1556.cpp

UVA_393_Doors_(线段相交+最短路)

描述 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=5&page=show_problem&problem=329 坐标系,x,y轴都是0~10.起点(0,5),终点(10,5),中间可能有墙,每一堵墙有两个门,给出门的上下定点的坐标,求从起点到终点的最短路. The Doors  You are to find the length of the shortes

POJ_1556_The Doors_判断线段相交+最短路

Description You are to find the length of the shortest path through a chamber containing obstructing walls. The chamber will always have sides at x = 0, x = 10, y = 0, and y = 10. The initial and final points of the path are always (0, 5) and (10, 5)

POJ 1556 The Doors(线段交+最短路)

#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> #include <map> #include <vector> #include <set> #include <string> #include <math.h> using namespac

poj 1066 线段相交

链接:http://poj.org/problem?id=1066 Treasure Hunt Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5431   Accepted: 2246 Description Archeologists from the Antiquities and Curios Museum (ACM) have flown to Egypt to examine the great pyramid

POJ 1066 Treasure Hunt(线段相交&amp;&amp;转换)

Treasure Hunt 大意:在一个矩形区域内,有n条线段,线段的端点是在矩形边上的,有一个特殊点,问从这个点到矩形边的最少经过的线段条数最少的书目,穿越只能在中点穿越. 思路:需要巧妙的转换一下这个问题,因为从一个点到终点不可能"绕过"围墙,只能穿过去,所以门是否开在中点是无所谓的,只要求四周线段中点到终点的线段与墙的最少交点个数即可.更进一步,实际上,只需判断四周围墙的所有点与终点的连线与内墙的最少交点加一即可. struct Point{ double x, y; } A,

线段相交 poj 1066

1 // 线段相交 poj 1066 2 // 思路:直接枚举每个端点和终点连成线段,判断和剩下的线段相交个数 3 4 // #include <bits/stdc++.h> 5 #include <iostream> 6 #include <cstdio> 7 #include <cstdlib> 8 #include <algorithm> 9 #include <vector> 10 #include <math.h>

poj 3304 直线与线段相交

Segments Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12161   Accepted: 3847 Description Given n segments in the two dimensional space, write a program, which determines if there exists a line such that after projecting these segments

poj 2653 线段与线段相交

Pick-up sticks Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 11884   Accepted: 4499 Description Stan has n sticks of various length. He throws them one at a time on the floor in a random way. After finishing throwing, Stan tries to fin