标签:
题目大意:起点坐标(0,5),终点坐标(10,5),在这两点之间有着n道墙,每道墙有两个门
求起点到终点的最短距离
思路:构图,floyed算法,此题主要是判断两点是否连通,及判断线段相交,我通过题目给出的数据构造了3*n条线段
因为每一道墙2个门,及相对的有3条线段,用两点在他们之间的所有线段都判断一次是否相交
代码如下:
#include <iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; const int maxs = 100; const float INF = 0x3f3f3f3f; const float eps = 1e-6; typedef struct { float x; float y; }Point; typedef struct { Point s; Point e; }Line; Point points[maxs];//points[0]起点,points[nums-1]终点 Line lines[maxs];//线段标号从1开始 float X[maxs]; int N,nums,counts;//N:墙的数目,nums:点的总个数,counts:线段的条数-障碍物 float A[maxs][maxs]; void getLine() { //把除起点和终点外的所有点构成线段,每一道墙3条线段 Point temp1,temp2; int k; for(int i=1;i<=N*3;i=i+3) { k=i/3+1; temp1.x=X[k];temp1.y=0; temp2.x=X[k];temp2.y=10; lines[i].s=temp1; lines[i].e=points[k*4-3]; lines[i+1].s=points[k*4-2]; lines[i+1].e=points[k*4-1]; lines[i+2].s=points[k*4-0]; lines[i+2].e=temp2; } counts=N*3; } float dis(Point point1,Point point2) { float d1 = point1.x-point2.x; float d2 = point1.y-point2.y; return sqrt(d1*d1+d2*d2); } bool isCross(Point a,Point b,Line line) { //该线段不在a,b两点之间,不相交 if(line.s.x<=a.x||line.s.x>=b.x) return false; //交点已知横坐标,根据横坐标算出交点纵坐标 float x = line.e.x; float k = (a.y-b.y)/(a.x-b.x); float y = k*(x-a.x)+a.y; if(y-line.s.y>eps&&line.e.y-y>eps) return true; return false; } //判断两点之间是否可以连通,连通true bool judge(Point a,Point b) { //找出所有在这两点之间的线段,线段的横坐标大于起点,小于终点 //a的横坐标比b的小,如果相等说明在同一道墙上,先假定相交后面再判断 if(a.x==b.x) return false; int i=1,j=counts; // while(lines[i].s.x<=a.x&&i<counts) i=i+3; // while(lines[j].s.x>=b.x&&j>1) j=j-3; for(int k=i;k<=j;k++) if(isCross(a,b,lines[k])) return false; return true; } void floyed() { for(int k=0;k<nums;k++) for(int i=0;i<nums;i++) for(int j=0;j<nums;j++) if(A[i][j]>A[i][k]+A[k][j]) A[i][j]=A[i][k]+A[k][j]; } int main() { //freopen("in.txt","r",stdin); while(scanf("%d",&N)!=EOF&&N!=-1) { nums=0; memset(points,0,sizeof(points)); memset(lines,0,sizeof(lines)); points[nums].x=0;points[nums].y=5; for(int i=1;i<=N;i++) { scanf("%f",&X[i]); for(int j=1;j<=4;j++) { points[++nums].x=X[i]; scanf("%f",&points[nums].y); } } points[++nums].x=10;points[nums].y=5; nums++; //初始化距离 for(int i=0;i<nums;i++) for(int j=0;j<nums;j++) if(i==j) A[i][j]=0; else A[i][j]=INF; //初始化线段 getLine(); //对于起点的判断 for(int i=1;i<nums;i++) if(judge(points[0],points[i])) { A[0][i]=dis(points[0],points[i]); A[i][0]=dis(points[0],points[i]); } //对于其它任意不在同一道墙间的点判断 for(int i=1;i<nums;i++) { for(int j=i+1;j<nums;j++) { if(judge(points[i],points[j])) { A[i][j]=dis(points[i],points[j]); A[j][i]=dis(points[i],points[j]); } } } for(int i=1;i<=N;i++) { //1-2连通,3-4连通,以此类推 int index1 = i*4-3; int index2 = i*4-2; int index3 = i*4-1; int index4 = i*4; A[index1][index2]=A[index2][index1]=dis(points[index1],points[index2]); A[index3][index4]=A[index4][index3]=dis(points[index3],points[index4]); } floyed(); printf("%.2f\n",A[0][nums-1]); } return 0; }
标签:
原文地址:http://www.cnblogs.com/wt20/p/5738633.html