题意:有一个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; }