zoukankan      html  css  js  c++  java
  • 四大求图的最短路径方法(上)

    一个图一般都带有权值,而求一个点到另一个点的距离,则是比较基础的问题,下面为大家介绍四种遍历图的方法


    一、弗洛伊德算法(暴力枚举法)

    首先使用数组dis [ i ] [ j ],i,j表示从 i 到 j 的距离,刚开始 i 和 j 没有联系时,初始化为无限(1<<30),输入后仍没联系时,通过中间点 k 来计算 dis[ i ] [ j ] = dis[ i ] [ k ] + dis[ k ] [ j ],需要三重循环(讲例题时在再看代码实现)


    二、迪杰斯克拉算法(抄水表法)

    在知道起点和终点的情况下,设定数组dis [ i ],表示从起点到 i 点的距离,从起点开始,一家一家的查找能与之相连的点(抄水表),再将已被查过的点做起点,继续抄水表(注意:抄过的家就不用抄了,所以要设一个bool数组),注意除起点外,其他dis都初始化为1<<30(讲例题时在再看代码实现)


    下面来看一道例题:

    最短路径问题

    题目描述

    平面上有n个点(n<=100),每个点的坐标均在-10000~10000之间。其中的一些点之间有连线。若有连线,则表示可从一个点到达另一个点,即两点间有通路,通路的距离为两点间的直线距离。现在的任务是找出从一点到另一点之间的最短路径。

    输入

    第1行:1个整数n

    第2..n+1行:每行2个整数x和y,描述了一个点的坐标

    第n+2行:1个整数m,表示图中连线的数量

    接下来有m行,每行2个整数i和j,表示第i个点和第j个点之间有连线

    最后1行:2个整数s和t,分别表示源点和目标点

    输出

    第1行:1个浮点数,表示从s到t的最短路径长度,保留2位小数

    样例输入

    5
    0 0
    2 0
    2 2
    0 2
    3 1
    5
    1 2
    1 3
    1 4
    2 5
    3 5
    1 5
    

    样例输出

    3.41


    这道题两种方法都可以做,注意求两点A,B距离的方法AB=sqrt( pow( Xa - Xb ) + pow( Ya - Yb ) ),就是勾股定理


    好,不说了,来看代码:


    弗洛伊德算法:

    <span style="font-size:14px;background-color: rgb(255, 255, 153);">#include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    double d[101][101];
    int n,m,b,e;
    void scan()//输入加初始化
    {
    	int i,j,x,y;
    	double z[101][2];
    	scanf("%d",&n);
    	for(i=1;i<=n;i++)
    		for(j=1;j<=n;j++)
    			d[i][j]=1<<29;
    	for(i=1;i<=n;i++)
    		scanf("%lf%lf",&z[i][0],&z[i][1]);
    	scanf("%d",&m);
    	for(i=1;i<=m;i++)
    	{
    		scanf("%d%d",&x,&y);
    		d[x][y]=d[y][x]=sqrt(pow(z[x][0]-z[y][0],2)+pow(z[x][1]-z[y][1],2));//计算两点距离公式
    	}
    	scanf("%d%d",&b,&e);
    	d[b][b]=0;
    }
    void work()//弗洛伊德算法
    {
    	int j,i,k;
    	for(k=1;k<=n;k++)
    		for(i=1;i<=n;i++)
    			for(j=1;j<=n;j++)
    				d[i][j]=min(d[i][j],d[i][k]+d[j][k]);//找最短路径
    }
    int main()
    {
    	scan();
    	work();
    	printf("%.2lf",d[b][e]);//输出从b到e的距离
    }</span>

    这就是传说中的暴力枚举


    迪杰斯克拉算法:

    <span style="font-size:14px;background-color: rgb(255, 255, 153);">#include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    double d[101],w[101][101];
    bool v[101];
    int n,m,b,e;
    void scan()
    {
    	int i,x,y;
    	double z[101][2];
    	memset(d,127,sizeof(d));
    	memset(w,127,sizeof(w));
    	scanf("%d",&n);
    	for(i=1;i<=n;i++)
    		scanf("%lf%lf",&z[i][0],&z[i][1]);
    	scanf("%d",&m);
    	for(i=1;i<=m;i++)
    	{
    		scanf("%d%d",&x,&y);
    		w[x][y]=w[y][x]=sqrt(pow(z[x][0]-z[y][0],2)+pow(z[x][1]-z[y][1],2));
    	}
    	scanf("%d%d",&b,&e);
    	d[b]=0;
    }
    void work()
    {
    	int j,i;
    	for(i=1;i<=n;i++)
    	{
    		double minn=100000;
    		int minx;
    		for(j=1;j<=n;j++)
    			if(!v[j]&&minn>d[j])//抄水表式找点
    			{
    				minx=j;
    				minn=d[j];
    			}
    		v[minx]=1;
    		for(j=1;j<=n;j++)
    			d[j]=min(d[j],d[minx]+w[minx][j]);//判断最短路
    	}
    }
    int main()
    {
    	freopen("dijkstra.in","r",stdin);
    	freopen("dijkstra.out","w",stdout);
    	scan();
    	work();
    	printf("%.2lf",d[e]);//从起点到e
    }</span>

    抄水表啊!!!


    好了,今天只介绍这两种方法了,明天再来介绍后两种吧~(≧▽≦)/~

  • 相关阅读:
    错误: 找不到或无法加载主类/java BB.class 中文乱码
    如何新建git仓库并连接以及git branch相关命令
    String、StringBuffer与StringBuilder区别
    HTML选择器
    java中的system.out.println()和JSP中out.println()区别
    校园双选会,你都懂么
    android visible invisible和gone的区别
    Android 显示意图和隐式意图的区别
    android doGet和doPost
    Android 监听SMS短信
  • 原文地址:https://www.cnblogs.com/Darknesses/p/12002569.html
Copyright © 2011-2022 走看看