您的位置:首页 > 其它

POJ 1556 The Doors 线段判交+Dijkstra

2015-04-02 21:13 225 查看
The Doors

Time Limit: 1000MSMemory Limit: 10000K
Total Submissions: 6734Accepted: 2670
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). There will also be from 0 to 18 vertical walls inside the chamber, each with two doorways. The figure below illustrates such a chamber and also shows the path of minimal length.

/*************************************************************************
> File Name: poj_1556.cpp
> Author:
> Mail:
> Created Time: 2015年04月02日 星期四 14时55分17秒
************************************************************************/

#include<iostream>
#include <cstdio>
#include <cstring>
#include <math.h>
using namespace std;
const int N = 100;
const int INF = 99999999;
struct point{
double x, y;
};
point p
;
double dis
;
double Map

;
bool vis
;
int n;
double getDistance(int i, int j)//得到两个点之间的距离
{
return sqrt((p[i].x - p[j].x) * (p[i].x - p[j].x) + (p[i].y - p[j].y) * (p[i].y - p[j].y));
}
double getDirection(point a, point b, point c)//判断c与直线ab的关系
{
point t1, t2;
t1.x = c.x - a.x; t1.y = c.y - a.y;
t2.x = b.x - a.x; t2.y = b.y - a.y;
return (t1.x * t2.y - t1.y * t2.x);
}
bool segment_intersect(point a, point b, point c, point d)//判断线段是否相交
{
double d1 = getDirection(a, b, c);
double d2 = getDirection(a, b, d);
double d3 = getDirection(c, d, a);
double d4 = getDirection(c, d, b);
if (d1 * d2 < 0 && d3 * d4 < 0)
return true;
return false;
}
bool isCross(int a, int b)//判断两点之间是否有墙阻隔
{
point t1, t2;
int i;
if (a == 0)
i = 1;
else
i = a / 4 + (a % 4 != 0) + 1;
for (; i < b / 4 + (b % 4 != 0); i++)
{
t1.x = p[4 * i - 3].x;
t1.y = 0;
t2.x = t1.x; t2.y = 10.0;
if (segment_intersect(t1, p[4 * i - 3], p[a], p[b]) || segment_intersect(p[4 * i - 2], p[4 * i - 1], p[a], p[b])
|| segment_intersect(p[4 * i], t2, p[a], p[b]))
return true;

}
return false;
}
void Dijkstra()//单源最短路径
{
memset(vis, false, sizeof(vis));
int m = 4 * n + 2;
for (int i = 0; i < m; i++)
dis[i] = Map[0][i];
dis[0] = 0;
vis[0] = true;
double min;
int k;
for (int i = 1; i < m; i++)
{
min = INF;
for (int j = 0; j < m; j++)
{
if (!vis[j] && min > dis[j])
{
k = j;
min = dis[j];
}
}
vis[k] = true;
for (int j = 0; j < m; j++)
{
if (!vis[j] && dis[j] > dis[k] + Map[k][j])
dis[j] = dis[k] + Map[k][j];
}

}
}
int main()
{
while (~scanf("%d", &n) && n != -1)
{
double a, b, c, d, e;
p[0].x = 0; p[0].y = 5;
p[4 * n + 1].x = 10; p[4 * n + 1].y = 5;//一共4*n+2个点
for (int i = 1; i <= 4 * n; i++)
{
scanf("%lf %lf %lf %lf %lf", &a, &b, &c, &d, &e);
p[i].x = a; p[i].y = b;
p[++i].x = a; p[i].y = c;
p[++i].x = a; p[i].y = d;
p[++i].x = a; p[i].y = e;
}
for (int i = 0; i < 4 * n + 2; i++)
{
for (int j = 0; j < 4 * n + 2; j++)
if (i != j)
Map[i][j] = INF;
else
Map[i][j] = 0;
}
for (int i = 0; i < 4 * n + 2; i++)//建立地图
{
for (int j = i + 1; j < 4 * n + 2; j++)
{
if (!isCross(i, j))
Map[i][j] = getDistance(i, j);
}
}
Dijkstra();//求最短路径
printf("%.2f\n", dis[4 * n + 1]);

}

return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: