题意:

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

分析:

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

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

 #include <cstdio>
#include <cmath>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std; const int maxn = ;
const double INF = 1e4;
const double eps = 1e-; struct Point
{
double x, y;
Point(double x=, double y=):x(x), y(y) {}
}p[maxn * ]; typedef Point Vector; Point read_point()
{
double x, y;
scanf("%lf%lf", &x, &y);
return Point(x, y);
} Point operator - (const Point& A, const Point& B)
{ return Point(A.x-B.x, A.y-B.y); } Vector operator / (const Vector& A, double p)
{ return Vector(A.x/p, A.y/p); } double Dot(const Vector& A, const Vector& B)
{ return A.x*B.x + A.y*B.y; } double Length(const Vector& A)
{ return sqrt(Dot(A, A)); } struct Door
{
double x, y1, y2, y3, y4;
Door(double x=, double y1=, double y2=, double y3=, double y4=):x(x), y1(y1), y2(y2), y3(y3), y4(y4) {}
}; vector<Door> door; double d[maxn * ], w[maxn * ][maxn * ];
bool vis[maxn * ];
int cnt; bool isOK(int a, int b)
{//判断两点是否能直接到达
if(p[a].x >= p[b].x) swap(a, b);
for(int i = ; i < door.size(); ++i)
{
if(door[i].x <= p[a].x) continue;
if(door[i].x >= p[b].x) break;
double k = (p[b].y-p[a].y) / (p[b].x-p[a].x);
double y = p[a].y + k * (door[i].x - p[a].x);
if(!(y>=door[i].y1&&y<=door[i].y2 || y>=door[i].y3&&y<=door[i].y4)) return false;
}
return true;
} void Init()
{
for(int i = ; i < cnt; ++i)
for(int j = i; j < cnt; ++j)
if(i == j) w[i][j] = ;
else w[i][j] = w[j][i] = INF;
} int main()
{
//freopen("in.txt", "r", stdin); int n;
while(scanf("%d", &n) == && n + )
{
door.clear();
memset(vis, false, sizeof(vis));
memset(d, , sizeof(d)); p[] = Point(, );
cnt = ;
for(int i = ; i < n; ++i)
{
double x, y[];
scanf("%lf", &x);
for(int j = ; j < ; ++j) { scanf("%lf", &y[j]); p[cnt++] = Point(x, y[j]); }
door.push_back(Door(x, y[], y[], y[], y[]));
}
p[cnt++] = Point(, ); Init(); for(int i = ; i < cnt; ++i)
for(int j = i+; j < cnt; ++j)
{
double l = Length(Vector(p[i]-p[j]));
if(p[i].x == p[j].x) continue;
if(isOK(i, j))
w[i][j] = w[j][i] = l;
}
//Dijkstra
d[] = ;
for(int i = ; i < cnt; ++i) d[i] = INF;
for(int i = ; i < cnt; ++i)
{
int x;
double m = INF;
for(int y = ; y < cnt; ++y) if(!vis[y] && d[y] <= m) m = d[x=y];
vis[x] = ;
for(int y = ; y < cnt; ++y) d[y] = min(d[y], d[x] + w[x][y]);
} printf("%.2f\n", d[cnt-]);
} return ;
}

代码君

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

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

    POJ_1556_The Doors_判断线段相交+最短路 Description You are to find the length of the shortest path through a ...

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

    题目传送门 题意:从(0, 5)走到(10, 5),中间有一些门,走的路是直线,问最短的距离 分析:关键是建图,可以保存所有的点,两点连通的条件是线段和中间的线段都不相交,建立有向图,然后用Dijks ...

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

    题目: Description You are to find the length of the shortest path through a chamber containing obstruc ...

  4. POJ 2556 (判断线段相交 + 最短路)

    题目: 传送门 题意:在一个左小角坐标为(0, 0),右上角坐标为(10, 10)的房间里,有 n 堵墙,每堵墙都有两个门.每堵墙的输入方式为 x, y1, y2, y3, y4,x 是墙的横坐标,第 ...

  5. POJ 1556 计算几何 判断线段相交 最短路

    题意: 在一个左下角坐标为(0,0),右上角坐标为(10,10)的矩形内,起点为(0,5),终点为(10,5),中间会有许多扇垂直于x轴的门,求从起点到终点在能走的情况下的最短距离. 分析: 既然是求 ...

  6. POJ 1556 The Doors【最短路+线段相交】

    思路:暴力判断每个点连成的线段是否被墙挡住,构建图.求最短路. 思路很简单,但是实现比较复杂,模版一定要可靠. #include<stdio.h> #include<string.h ...

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

    The Doors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5210   Accepted: 2124 Descrip ...

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

    #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm& ...

  9. poj 1066 线段相交

    链接:http://poj.org/problem?id=1066 Treasure Hunt Time Limit: 1000MS   Memory Limit: 10000K Total Subm ...

随机推荐

  1. 【转】How to view word document in WPF application

    How to view word document in WPF application (CSVSTOViewWordInWPF) Introduction The Sample demonstra ...

  2. bootstrap IE兼容

    <meta name="viewport" content="width=device-width, initial-scale=1">     & ...

  3. javascript event兼容IE和FF

    事件对象在IE和FF下的兼容写法 function abc(event){ var e=event||window.event; //键盘码的捕获 var key=e.which||e.keyCode ...

  4. Selenium+python+shell+crontab+firefox

    最近在尝试一个自动打卡的脚本,发现了几个问题,特此记录一下. 环境: Ubuntu 12.04.4 LTS selenium 2.43.0 firefox 32.0.3 1 本来机器上selenium ...

  5. 二、mysql数据类型

    .数值型 ) decimal最大支持65位 ) 最大支持10位的二进制存储模式 bin(column),hex(column) 使用bin(二进制查看)或hex(十六进制查看)查看bit类型数据 .时 ...

  6. csharp excel interop programming

    string fileName = "c:\\a.xlsx"; var application = new Application(); application.Visible = ...

  7. poj 3463 Sightseeing( 最短路与次短路)

    http://poj.org/problem?id=3463 Sightseeing Time Limit: 2000MS   Memory Limit: 65536K Total Submissio ...

  8. 使用Unity拦截一个返回Task的方法

    目标 主要是想为服务方法注入公用的异常处理代码,从而使得业务代码简洁.本人使用Unity.Interception主键来达到这个目标.由于希望默认就执行拦截,所以使用了虚方法拦截器.要实现拦截,需要实 ...

  9. 【概率】COGS 1487:麻球繁衍

    Description 万有引力定律: “使物体相互靠近的力的大小与物体的质量成正比——而物体的质量又由同一种力决定.这是一个有趣并且有益的例子,说明了科学是如何用A证明B,再用B证明A的.”——安布 ...

  10. spoj 379

    题是水题  但丫的题目意思太难懂 .......   英语水平  ...... #include <cstdio> #include <cstring> #include &l ...