- ドア
この質問は地図を作成するのが最も難しいと考えて、最短パスの地図作成が出てくるのを見つけます。たとえば、私の地図作成方法では、まず最初に、配列の始点と終点、および各セグメントの終点を壁として配置します。グラフの頂点(意味がないため、壁のルートの2つのポイントを削除します)。次に、seg [] []配列を使用して、各壁の各ラインセグメントの情報を表します。seg[i] []は、i番目の壁の情報を表します。この配列の目的は、主に次のとおりです。pos[]配列の2点ごとにトラバースするエッジを構築できるかどうかを判断します。これらの2つのポイントによって形成されるラインセグメントが、間の壁によってブロックされている場合(壁の特定のラインセグメントと交差している場合)、エッジを構築できません。そうでない場合、エッジが構築されます。
ここでは、ラインセグメントabとcdが交差するかどうかを判断する方法について説明します。
2つの線セグメントが交差する場合、ca⃗×cb⃗\ vec {ca} \ times \ vec {cb}があります。c a
××c b
和DA⃗×DB⃗\ VEC {DA} \回\ VEC {DB}d a
××d b
異なる符号とda⃗×ca⃗\ vec {da} \ times \ vec {ca}d a
××c a
そしてdb⃗×cb⃗\ vec {db} \ times \ vec {cb}d b
××c b
これも逆の符号です。この2つの条件が同時に満たされると交差点になります。1つの条件が満たされると書いただけですが、線分が交差するかどうかを判断するのに十分な条件ではありません。今知りました。
- コード
#pragma GCC optimize(2)
#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){
if(fuck(a,c,b)*fuck(a,d,b)<eps)
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()
{
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;
}