题意:有一个10*10的矩形,你在(0,5),要走到(10,5),中间有一些障碍阻挡,障碍都是平行于y轴的,中间有两个区间是“门”,可以通过,求最短路径。
思路:先建图,最短路径肯定是贴着门边的,如果两个顶点(门边)之间没有线段阻挡,连接这两个顶点。然后根据建好的图求最短路。这个题我做了三天。。。因为中间有个很2的逻辑错误一直没有发现。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <ctype.h>
using namespace std;
double wall[20][4];
double wallx[20];
double a[80];
struct point{
double x;
double y;
point(double xx,double yy){
x=xx;
y=yy;
}
};
bool cp(double xa,double ya,double xb,double yb){//向量叉积
return (xa*yb-xb*ya)<0;
}
bool judge(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4){//线段判交
//printf("检测(%lf,%lf),(%lf,%lf)和(%lf,%lf),(%lf,%lf)的相交情况.\n",x1,y1,x2,y2,x3,y3,x4,y4);
bool re=(cp(x2-x1,y2-y1,x3-x1,y3-y1)!=cp(x2-x1,y2-y1,x4-x1,y4-y1))&&(cp(x4-x3,y4-y3,x1-x3,y1-y3)!=cp(x4-x3,y4-y3,x2-x3,y2-y3));
return re;
}
double dist(double x1,double y1,double x2,double y2){//两点间距离
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
struct edge{
int next;
double weight;
edge(int n,double w){
next=n;
weight=w;
}
};
int main(){
int n;
while(~scanf("%d",&n)){
if(n==-1)break;
vector<edge> v[80];
//输入
for(int i=1;i<=n;i++){
scanf("%lf",&wallx[i]);
for(int j=0;j<4;j++){
scanf("%lf",&wall[i][j]);
}
}
wallx[0]=0.0;
wall[0][0]=wall[0][1]=wall[0][2]=wall[0][3]=5.0;
wallx[n+1]=10.0;
wall[n+1][0]=wall[n+1][1]=wall[n+1][2]=wall[n+1][3]=5.0;
//建图
queue<int> que;
que.push(0);
while(!que.empty()){
int cur=que.front();
que.pop();
int curx,cury;
if(cur==0){
curx=0;
cury=0;
}else{
curx=(cur-1)/4+1;
cury=(cur-1)%4;
}
if(!v[cur].empty())continue;
for(int i=curx+1;i<=n+1;i++){//n个墙壁
for(int k=0;k<4;k++){//4个顶点
bool flag=true;
for(int j=curx+1;j<i;j++){//扫描之前的墙壁
if( judge(wallx[curx],wall[curx][cury],wallx[i],wall[i][k], wallx[j],0.0,wallx[j],wall[j][0])){
flag=false;
break;
}
if( judge(wallx[curx],wall[curx][cury],wallx[i],wall[i][k], wallx[j],wall[j][1],wallx[j],wall[j][2])){
flag=false;
break;
}
if( judge(wallx[curx],wall[curx][cury],wallx[i],wall[i][k], wallx[j],wall[j][3],wallx[j],10.0)){
flag=false;
break;
}
}
if(flag){//没有阻碍,可以连接
edge n((i-1)*4+k+1,dist(wallx[curx],wall[curx][cury],wallx[i],wall[i][k]));
v[cur].push_back(n);
que.push((i-1)*4+k+1);
//printf("连接(%lf,%lf)和(%lf,%lf)!\n",wallx[curx],wall[curx][cury],wallx[i],wall[i][k]);
}else{
//printf("连接失败.\n");
}
if(i==(n+1))break;
}
}
}
for(int i=0;i<80;i++){
a[i]=9999.9;
}
a[0]=0.0;
queue<int> que2;
que2.push(0);
while(!que2.empty()){
int cur=que2.front();
que2.pop();
for(int i=0;i<v[cur].size();i++){
if( (v[cur][i].weight+a[cur])<a[v[cur][i].next] ){
a[v[cur][i].next]=(v[cur][i].weight+a[cur]);
que2.push(v[cur][i].next);
}
}
}
// for(int i=0;i<=n*4+1;i++){
// cout<<a[i]<<endl;
// }
printf("%.2lf\n",a[n*4+1]);
}
return 0;
}