原题连接 https://www.luogu.org/problemnew/show/P1744ios
一道最短路的模板题.....很简单吧算法
求最短路的方法有不少,可是对于刚学完Floyd的我,只会用这个.......虽然有点慢,可是也能AC数组
Floyd算法闭包
1.定义概览spa
Floyd-Warshall算法(Floyd-Warshall algorithm)是解决任意两点间的最短路径的一种算法,能够正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包。Floyd-Warshall算法的时间复杂度为O(N3),空间复杂度为O(N2)。code
2.算法描述blog
算法思想原理:ci
Floyd算法是一个经典的动态规划算法。用通俗的语言来描述的话,首先咱们的目标是寻找从点i到点j的最短路径。从动态规划的角度看问题,咱们须要为这个目标从新作一个诠释(这个诠释正是动态规划最富创造力的精华所在)string
从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i通过若干个节点k到j。因此,咱们假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每个节点k,咱们检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,若是成立,证实从i到k再到j的路径比i直接到j的路径短,咱们便设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当咱们遍历完全部节点k,Dis(i,j)中记录的即是i到j的最短路径的距离。it
咱们能够开一个n*n的邻接矩阵,记录联通状况:f[i][j]若是为1,则说明i到j联通;若是为∞,则说明不连通(之因此用∞的缘由是比较的时候无穷大必定比任何除无穷大之外的数的和都大,这样就不会把∞算进去),而后能够进一步将f[i][j]=1的地方利用两点间距离公式将1换成具体的距离
代码以下:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> using namespace std; int n,m,x,y,a[101][2],aa,bb; //a数组存放坐标 double b[101][101]; //b数组存放最短路,注意double类型 int main() { cin>>n; //n个点 for(int i=1;i<=n;i++) cin>>a[i][0]>>a[i][1]; //横纵坐标 cin>>m; //m处联通 memset(b,0x7f,sizeof(b)); //先将所有的元素赋为无穷大 for(int i=1;i<=m;i++) { cin>>x>>y; //点x与点y是联通的 b[x][y]=b[y][x]=sqrt(pow((double)(a[x][0]-a[y][0]),2)+pow((double)(a[x][1]-a[y][1]),2)); //利用邻接矩阵的对称性减小一半运算,两点间距离公式算距离,注意改为double类型 } for(int k=1;k<=n;k++) //Floyd算法,O(n^3)复杂度 for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i!=j&&i!=k&&j!=k&&((b[i][k]+b[k][j])<b[i][j])) b[i][j]=b[i][k]+b[k][j]; //若是第i点和第j点间有个间接点k使得第i个点到第k个点的距离+k个点到第j个点的距离<小于第i个点到第j个点的直接距离,则将最短距离更新 cin>>aa>>bb; //题目要求的第aa个点到第bb个点的矩阵 printf("%.2lf",b[aa][bb]); //直接输出 return 0; }
完结撒花qaq~