您的位置:首页 > 其它

【解题报告】 POJ 1556 The Doors -- 最短路问题 Dijkstra算法 + 直线相交

2012-09-05 23:15 323 查看
题目连接:POJ 1556

题目大意:从房间的坐标(0,5) -> (10,5),中间经过最多不超过18个墙,求路径最短。

这道题在nyoj上AC不了,貌似数据中墙会重复输入 ( waiting... )

// POJ 1556 The Doors  -- 最短路问题 Dijkstra算法 + 直线相交
// PS : 自我感觉Dijkstra算法类似于 BFS
//
/*test data
2
4 2 7 8 9
7 3 4.5 6 7
1
5 4 6 7 8
5
4 0 1 2 3
4.5 0 0.5 0.8 1
5 4 6 7 8
7 2 4.6 5 6
9 1.5 2.5 5.5 7.5
-1

=14.56
10.06
10.00
*/

#include <stdio.h>
#include <math.h>
#include <algorithm>
using namespace std;

const double infiniteS = 0.000001;
const int infinite = (1<<30); // 无穷大
const int MAXP = 200; //74

struct POINT{
double x,y;
}p[MAXP];
double d[MAXP];
int n;

double Abs(double a){
return (a>=0)?(a):(-a);
}

bool comp(POINT A,POINT B){ // 按 x 排序
if (Abs(A.x - B.x) < infiniteS)
return A.y < B.y;
else
return A.x < B.x;
}
double Distance(double x1,double y1,double x2,double y2){
return sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) );
}

double XJ(POINT p0,POINT p1, POINT p2,POINT p3){
// 一般情况下计算 p0 p1 X p2 p3 的叉积
// (p1.x-p0.x, p1.y-p0.y) vector|p0p1|
// (p3.x-p2.x, p3.y-p2.y) vector|p2p3|
double res = (p1.x-p0.x)*(p2.y-p0.y) - (p3.x-p2.x)*(p3.y-p2.y);
return res;
}
int XJ(POINT p0,POINT p1, POINT p2){
// p0 p1 p2 顺时针 为正输出1 ,否则-1 ,一条直线上为0
// p0 p1 ->  p0 p2
// (p1.x-p0.x, p1.y-p0.y) vector|p0p1|
// (p2.x-p0.x, p2.y-p0.y) vector|p0p2|
double res = (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y);
return (res > infiniteS)?(1):(-1);
}

bool Segment(POINT a, POINT b, POINT c, POINT d){
// 说明是 1^-1=-2, 存在两个跨立则判定为线段相交
return ((XJ(a,b,c)^XJ(a,b,d))==-2) && ((XJ(a,c,d)^XJ(b,c,d))==-2);
}

bool ExisTobstacle(int p1,int p2){ // 判断两个点之间有障碍
double left_x = p[p1].x, right_x = p[p2].x;
for (int i = p1 + 1; i < p2; i++){
if (Abs(p[i].x - left_x) <= infiniteS)continue;
if (Abs(p[i].x - right_x) <= infiniteS)break;
POINT a,b; // a i   i+1 i+2   i+3 b
a.y = 0; b.y = 10;
a.x = b.x = p[i].x;
if (Segment(a, p[i], p[p1], p[p2]) ||
Segment(p[i+1], p[i+2], p[p1], p[p2]) ||
Segment(p[i+3], b, p[p1], p[p2])	){
// 只要与墙有交点 则存在障碍
return true;
}
i+=3;
}
return false;
}

double Dijkstra(int np){ // (0,5) -> (10,5) 的最短路
for (int i = 0; i < np; i++){
for (int j = i + 1; j < np; j++){
if (p[i].x == p[j].x || ExisTobstacle(i,j) )
continue;

double dis = Distance(p[i].x,p[i].y,p[j].x,p[j].y);
if (dis + d[i] < d[j]){
d[j] = dis + d[i];
}
}
}
return d[np-1];
}

int init(int n){
for (int i = 0; i < MAXP;i++){
d[i] = infinite;
}
d[0]=0;
p[0].x=0;p[0].y=5;
int psub=1;
for (int i = 0; i < n; i++){ // p[]: 0 1  2 3    4 5  6 7 ....
double tempx;
scanf("%lf",&tempx);
for (int j = 0 ; j < 4; j++){
scanf("%lf",&p[psub].y);
p[psub++].x = tempx;
}
}p[psub].x = 10;	p[psub++].y = 5;
return psub;
}

int main()
{
//	freopen("in.txt","r",stdin);

while(scanf("%d",&n), n+1){
if (n==0){
printf("10.00\n");continue;
}
int psub = init(n);	// 初始化

sort(&p[0],&p[n-1],comp);
printf("%.2lf\n",Dijkstra(psub));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: