POJ The Doors (Composición + Camino más corto)

  • Las puertas
  • Pensando que
    Figura 1
    esta pregunta es la más difícil de construir un mapa, encontrar un mapa de ruta más corto saldrá después, digamos, bajo mi método de construcción de mapas, en primer lugar, la matriz pos [] comenzará y terminará el punto y el punto final de cada segmento como una pared Los vértices del gráfico (elimine los dos puntos de la raíz de la pared, porque no tiene sentido). Luego use la matriz seg [] [] para representar la información de cada segmento de línea de cada pared, seg [i] [] representa la información de la i-ésima pared, el propósito de esta matriz es principalmente: atravesar cada dos puntos de la matriz pos [] Juzgue si el borde se puede construir Si el segmento de línea formado por estos dos puntos está bloqueado por el muro entre (intersectando un cierto segmento de línea en el muro), el borde no se puede construir, de lo contrario se construye el borde.
    Aquí hablaré sobre cómo juzgar si los segmentos de línea ab y cd se intersecan.

    Si dos segmentos de línea se cruzan, hay ca ⃗ × cb ⃗ \ vec {ca} \ times \ vec {cb}c a ×c b da ⃗ × db ⃗ \ vec {da} \ times \ vec {db}d a ×d b Signo diferente y da ⃗ × ca ⃗ \ vec {da} \ times \ vec {ca}d a ×c a Y db ⃗ × cb ⃗ \ vec {db} \ times \ vec {cb}d b ×c b También es un signo opuesto. Si estas dos condiciones se cumplen al mismo tiempo, es la intersección. Solo escribí que se cumple una condición, pero esta no es una condición suficiente para juzgar la intersección de los segmentos de línea. Esto se debe a que los datos proporcionados en esta pregunta son especiales. Espero que todos Sólo sé.
  • Código
#pragma GCC optimize(2)
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<cstring> 
 
using namespace std;

typedef long long ll;
typedef unsigned long ul;
typedef unsigned long long ull;
#define pi acos(-1.0)
#define e exp(1.0)
#define pb push_back
#define mk make_pair
#define fir first
#define sec second
#define scf scanf
#define prf printf
typedef pair<double,int> pa;
const double INF=0x3f3f3f3f;
const double eps=1e-8;
const int MAX_I=1000;//墙的数量 
const int MAX_N=MAX_I*7;//点的数量 
const int MAX_M=MAX_N<<1;//边的数量 
int head[MAX_N],e_cnt,N,cnt=0;; 
double d[MAX_N];
struct node{
    
    
	double x,y; 
}seg[MAX_I][6];//记录线段 
struct node_p{
    
    
	double x,y;
	int id;//对应一个顶点编号,便于后面建图 
	int bel;//属于哪一个墙 
}pos[MAX_N];//记录点的信息 
double dis_(node_p a,node_p b){
    
    
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
struct Edge{
    
    
	int to,next;
	double val;
}edge[MAX_M];
void add_edge(int u,int v,double dis){
    
    
	edge[e_cnt].to=v;
	edge[e_cnt].val=dis;
	edge[e_cnt].next=head[u];
	head[u]=e_cnt++;
	return ;
}
double fuck(node_p a,node c,node_p b){
    
    //计算叉乘 
	double x1,y1,x2,y2;
	x1=a.x-c.x;
	y1=a.y-c.y;
	x2=b.x-c.x;
	y2=b.y-c.y;
	return x1*y2-x2*y1;
}
bool is_inter(node_p a,node_p b,node c,node d){
    
    //叉乘判断线段a-b和c-d是否相交,如果相交,返回1 
	if(fuck(a,c,b)*fuck(a,d,b)<eps)//相乘结果小于0,说明是相交的 
	return 1;
	return 0;
}
//求最短路 
priority_queue<pa,vector<pa>,greater<pa> >Q;
void Dijkstra(int s){
    
    
	int i,j,k;
	for(i=0;i<cnt;i++)
	d[i]=INF;
	d[s]=0;
	while(!Q.empty())
	Q.pop();
	Q.push({
    
    0,s});
	while(!Q.empty()){
    
    
		pa jie=Q.top();
		Q.pop();
		int v=jie.sec;
		if(d[v]<jie.fir)
		continue;
		for(i=head[v];~i;i=edge[i].next){
    
    
			if(d[edge[i].to]>d[v]+edge[i].val){
    
    
				d[edge[i].to]=d[v]+edge[i].val;
				Q.push({
    
    d[edge[i].to],edge[i].to});
			}
		}
	}
	return ;
}
int main()
{
    
    
//  freopen(".../.txt","w",stdout);
//  freopen(".../.txt","r",stdin);
//	ios::sync_with_stdio(false);
	while(~scf("%d",&N)&&N!=-1){
    
    
		int i,j,k,g;
		double x,y;
		cnt=0;
		//将起点存入 
		pos[cnt].x=0;
		pos[cnt].y=5;
		pos[cnt].bel=0;
		pos[cnt].id=cnt++;
		for(i=1;i<=N;i++){
    
    
			scf("%lf",&x);
			seg[i][0].x=x;
			seg[i][0].y=0;
			for(j=1;j<=4;j++){
    
    
				scf("%lf",&y);
				seg[i][j].x=x;
				seg[i][j].y=y;
				pos[cnt].x=x;
				pos[cnt].y=y;
				pos[cnt].bel=i;
				pos[cnt].id=cnt++;
			}
			seg[i][5].x=x;
			seg[i][5].y=10;
		}
		//将终点存入 
		pos[cnt].x=10;
		pos[cnt].y=5;
		pos[cnt].bel=N+1;
		pos[cnt].id=cnt++;
		//建图
		memset(head,-1,sizeof(head));
		e_cnt=0;
		for(i=0;i<cnt-1;i++){
    
    
			for(j=i+1;j<cnt;j++){
    
    
				if(pos[i].bel==pos[j].bel)//在同一个墙上的两个点
				continue;
				double dis=dis_(pos[i],pos[j]);
				if(pos[j].bel-pos[i].bel==1){
    
    //说明是相邻的墙,可以直接连成一条边 
					add_edge(pos[i].id,pos[j].id,dis);
					add_edge(pos[j].id,pos[i].id,dis);
					continue;
				}
				//判断这两个点有没有被线段隔开 
				bool flag=0;
				for(k=pos[i].bel+1;k<pos[j].bel;k++)//看看中间的墙能不能挡住他们
					for(g=0;g<=4;g+=2){
    
    // 每个墙的三条线段
						if(is_inter(pos[i],pos[j],seg[k][g],seg[k][g+1])){
    
    
							flag=1;
							break;
						}
					}
					if(flag)
					break;
				}
				if(!flag){
    
    
					add_edge(pos[i].id,pos[j].id,dis);
					add_edge(pos[j].id,pos[i].id,dis);				
				}
			}
		}
		//求最短路
		Dijkstra(0);
		prf("%.2f\n",d[cnt-1]);
	}
	return 0;
}

Supongo que te gusta

Origin blog.csdn.net/weixin_43311695/article/details/108843442
Recomendado
Clasificación