poj1556
题目大意:起点坐标(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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构