POJ 1556 The Doors(简单计算几何+最短路)

●赘述题目

10*10的房间内,有竖着的一些墙(不超过18个)。问从点(0,5)到(10,5)的最短路。

按照输入样例,输入的连续5个数,x,y1,y2,y3,y4,表示(x,0--y1),(x,y2--y3),(x,y4--10)是墙壁。

●题解

方法:建图(用到简单计算几何)+最短路

○记录下每个端点。

○包含起点,终点,以及每个墙的可以走的端点,如下图:

○然后枚举点,尝试两两组合连(线段)边,若该线不会撞在墙上,即不会与墙壁线段相交,就add_adge()。

效果图如下:

如何判断呢? 计算几何呗。我用的方法如下,须同时满足两个条件:

●代码

#include<cmath>
#include<cstdio>
#include<queue>
#include<cstring>
#include<iostream>
using namespace std;
const double eps=1e-8;
typedef pair<double,int> pii;
struct point{double x,y;}p[105];
struct seg{double x1,y1,x2,y2;}w[105];
struct vec{
	double x,y;
	double operator ^(const vec rtm) {return x*rtm.y-y*rtm.x;} //向量叉乘(模)
	vec operator -(const vec rtm) {return (vec){x-rtm.x,y-rtm.y};}
}v1,v2,v3,v4,v5,v6,v7,v8;
struct edge{
	int to; double co; int next;
}e[10005];
int head[105];
double d[105];
int n,dnt,snt,ent;
double dis(point a,point b) {return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
int sign(double a)
{
	if(fabs(a)<eps) return 0;
	return a>0?1:-1;
}
void add(int u,int v,double c)
{
	e[ent]=(edge){v,c,head[u]};head[u]=ent++;
	e[ent]=(edge){u,c,head[v]};head[v]=ent++;
}
void dijkstra()
{
	for(int i=1;i<=dnt;i++) d[i]=1e7+9;
	priority_queue<pii> q;
	q.push((pii){0,1});d[1]=0;
	while(!q.empty())
	{
		pii u=q.top();q.pop();
		if(d[u.second]<u.first) continue;
		for(int i=head[u.second];i!=-1;i=e[i].next)
		{
			int v=e[i].to;
			if(d[v]>d[u.second]+e[i].co)
			{
				d[v]=d[u.second]+e[i].co;
				q.push((pii){d[v],v});
			}
		}
	}
}
int main()
{
	p[++dnt]=(point){0,5}; p[++dnt]=(point){10,5};
	while(1)
	{
		memset(head,-1,sizeof(head));
		dnt=2;snt=0;ent=0;
		scanf("%d",&n);
		if(n==-1) break;
		double x,y1,y2,y3,y4;
		for(int i=1;i<=n;i++)
		{
			scanf("%f%f%f%f%f",&x,&y1,&y2,&y3,&y4);
			p[++dnt]=(point){x,y1}; p[++dnt]=(point){x,y2}; p[++dnt]=(point){x,y3}; p[++dnt]=(point){x,y4};
			w[++snt]=(seg){x,0,x,y1}; w[++snt]=(seg){x,y2,x,y3}; w[++snt]=(seg){x,y4,x,10};
		}
		bool fg;
		for(int i=1;i<dnt;i++) for(int j=i+1;j<=dnt;j++)
		{
			fg=1;
			for(int k=1;k<=snt;k++)
			{
				v1=(vec){p[i].x-w[k].x1,p[i].y-w[k].y1};
				v2=(vec){p[i].x-w[k].x2,p[i].y-w[k].y2};
				v3=(vec){p[j].x-w[k].x1,p[j].y-w[k].y1};
				v4=(vec){p[j].x-w[k].x2,p[j].y-w[k].y2};	

				v5=(vec){0,0}-v1;
				v6=(vec){0,0}-v3;
				v7=(vec){0,0}-v2;
				v8=(vec){0,0}-v4;
				if(sign((v1^v2)*(v3^v4))<0&&(sign(v5^v6)*(v7^v8))<0) {fg=0;break;}
			}
			if(fg) add(i,j,dis(p[i],p[j]));
		}
		dijkstra();
		printf("%.2f\n",d[2]);
	}
	return 0;
}
时间: 2024-10-14 20:20:35

POJ 1556 The Doors(简单计算几何+最短路)的相关文章

[日常摸鱼]UVA393 The Doors 简单计算几何+最短路

The  Boy Next   Doors 题意:给定一个固定大小的房间($x,y$的范围都是$[0,10]$),有$n$个墙壁作为障碍(都与横坐标轴垂直),每个墙壁都有两扇门分别用四个点来描述,起点终点固定在$(0,5)$和$(10,5)$,求起点到终点的最短路长度,$n<=18$ 题解: 我们把每堵墙的每一"段"作为一条线段,对任意两点$u,v$,如果两点间的连线不和其他线段相交,那我们从$u$走到$v$的最短距离就是他们的欧几里得距离,对所有点对都这么做一遍,处理出所有能够

POJ 1556 The Doors --几何,最短路

题意: 给一个正方形,从左边界的中点走到右边界的中点,中间有一些墙,问最短的距离是多少. 解法: 将起点,终点和所有墙的接触到空地的点存下来,然后两两之间如果没有线段(墙)阻隔,就建边,最后跑一个最短路SPFA,即可得出答案. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <a

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 1556 The Doors 计算几何+最短路

其实本题非常的无脑,无脑拍完1A,写到blog里只因为TM无脑拍也拍了很久啊= = #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdl

POJ 1556 - The Doors 线段相交不含端点

POJ 1556 - The Doors题意:    在 10x10 的空间里有很多垂直的墙,不能穿墙,问你从(0,5) 到 (10,5)的最短距离是多少.    分析:        要么直达,要么一定是墙的边缘点之间以及起始点.终点的连线.        所以先枚举墙上每一点到其他点的直线可达距离,就是要判定该线段是否与墙相交(不含端点).        然后最短路. 1 #include <iostream> 2 #include <cstdio> 3 #include &l

POJ 1556 The Doors 线段交 dijkstra

LINK 题意:在$10*10$的几何平面内,给出n条垂直x轴的线,且在线上开了两个口,起点为$(0, 5)$,终点为$(10, 5)$,问起点到终点不与其他线段相交的情况下的最小距离. 思路:将每个开口的两端点作为一个节点,再枚举点与点间能否直接到达(判相交),以此建图求最短路. /** @Date : 2017-07-11 16:17:31 * @FileName: POJ 1556 线段交+dijkstra 计算几何.cpp * @Platform: Windows * @Author :

POJ 1556 The Doors

计算几何+最短路 枚举线段是否相交建图,然后跑最短路 #include<cstdio> #include<cstring> #include<vector> #include<cmath> #include<queue> #include<algorithm> using namespace std; const int maxn=1000+10; const double eps=1e-8; int n; int totP,totL

简单几何(线段相交+最短路) 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

poj 1687 Buggy Sat 简单计算几何

暑期集训出的第一道一血 感觉自己萌萌哒…… 这道题本身并没有坑点 仅仅是翻译巨坑…… 解大腿在做B 安学长在做E 我闲着也没事 就一个词一个词翻译F…… 最后感觉…… 题干大多数都看不懂…… 也都没啥用…… 大概呢…… 就是给你n个点…… m条回路…… 问你哪条回路是最外面的…… 总之最后就是让你求哪个回路组成的图形面积最大…… 考点就是多边形面积公式…… 怕有误差就没加/2…… 好像加了也能过吧…… WA了两次 一次是选错点了 一次是第一个点和最后一个点顺序反了…… 1 #include<st