floyd算法--一个人的旅行

2017-07-27 22:37:32

writer:pprp

题目如下:

虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人(白马王子,^0^),很多事,还能丰富自己的阅历,
还可以看美丽的风景……草儿想去很多地方,她想要去东京铁塔看夜景,去威尼斯看电影,去阳明山上看海芋,去纽约纯粹看雪景,去巴黎喝咖啡写信,
去北京探望孟姜女……眼看寒假就快到了,这么一大段时间,可不能浪费啊,一定要给自己好好的放个假,可是也不能荒废了训练啊,所以草儿决定在要在最短的时间去一个自己想去的地方!
因为草儿的家在一个小镇上,没有火车经过,所以她只能去邻近的城市坐火车(好可怜啊~)。
Input
输入数据有多组,每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个,草儿想去的地方有D个;
接着有T行,每行有三个整数a,b,time,表示a,b城市之间的车程是time小时;(1=<(a,b)<=1000;a,b 之间可能有多条路)
接着的第T+1行有S个数,表示和草儿家相连的城市;
接着的第T+2行有D个数,表示草儿想去地方。
Output
输出草儿能去某个喜欢的城市的最短时间。
Sample Input
6 2 3
1 3 5
1 4 7
2 8 12
3 8 4
4 9 12
9 10 2
1 2
8 9 10
Sample Output
9

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>

#define MAXN 1000000
#define N 1010

using namespace std;

int map[N][N],s[N],e[N],maxx;
int T,S,D;

int floyd(void)
{
    int res = MAXN;
    for(int k = 1 ;  k <= maxx ; k++)
        for(int i = 1 ; i <= maxx ; i++)
            if(map[i][k]!=MAXN)   //为什么这里两个不能互换位置
                for(int j = 1; j <= maxx ; j++)
                {
                    map[i][j] = min(map[i][j], map[i][k]+map[k][j]) ;
                    if(s[i]&&e[j]&&res > map[i][j])
                        res = map[i][j];
                }
    return res;
}
int main()
{
    while(scanf("%d%d%d",&T,&S,&D)!=EOF)
    {

        memset(s,0,sizeof(s));
        memset(e,0,sizeof(e));
        //不能用memset(map,MAXN,sizeof(map));进行初始化,二维数组不能用这种方法;

       /*这种也不可行
        for(int i=1; i<=1000; i++) //初始化
            memset(map[i],MAXN, sizeof(map[i]));
        */
        for(int i=1; i<=1000; i++) //初始化
            for(int j=1; j<=1000; j++)
                map[i][j] = MAXN;

        int a,b,w;

        for(int i=1; i<=T; i++)
        {
            scanf("%d%d%d",&a,&b,&w);

            maxx=max(maxx,max(a,b));      //找到最大的城市数

            map[a][b]=w;             //初始化
        }
        for(int i=1; i<=S; i++)             //标记需要查找的城市
        {
            scanf("%d",&a);
            s[a]=1;
        }
        for(int i=1; i<=D; i++)              // 记录下来想去的地方的标记
        {
            scanf("%d",&a);
            e[a]=1;
        }
        printf("%d\n",floyd());
    }

    return 0;
}

```
核心代码部分及其优化:

```
int floyd(void)
{
    int res = MAXN;
    for(int k = 1 ;  k <= maxx ; k++)
        for(int i = 1 ; i <= maxx ; i++)
            if(map[i][k]!=MAXN)   //为什么这里两个不能互换位置
                for(int j = 1; j <= maxx ; j++)
                {
                    map[i][j] = min(map[i][j], map[i][k]+map[k][j]) ;
                    if(s[i]&&e[j]&&res > map[i][j])
                        res = map[i][j];
                }
    return res;
}
```
解释:map[i][k] 才是需要交换的地方,如果改成map[k][i]意思就不一样了

以上代码是错误的:
下面这个是正确的:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>

using namespace std;

const int MAXN = 999999;
const int N = 1010;

int map[N][N],s[N],e[N],maxx;
int T,S,D;

void floyd(void)
{

    for(int k = 1 ;  k <= maxx ; k++)
        for(int i = 1 ; i <= maxx ; i++)
            if(map[i][k]!=MAXN&&i!=k)
                for(int j = 1; j <= maxx ; j++)
                {
                    if(i!=j)
                        map[i][j] = min(map[i][j], map[i][k]+map[k][j]) ;
                }

}
int main()
{
    while(scanf("%d%d%d",&T,&S,&D)!=EOF)
    {

        memset(s,0,sizeof(s));
        memset(e,0,sizeof(e));

        for(int i=1; i<=1001; i++)
            for(int j=1; j<=1001; j++)
                if(i!=j)
                    map[i][j] = MAXN;
                else
                    map[i][j] = 0;

        int a,b,w;

        for(int i=1; i<=T; i++)
        {
            cin >> a >> b >> w;
            if(w < map[a][b])
                map[a][b] = map[b][a] = w;
            maxx=max(maxx,max(a,b));
        }

        for(int i = 1; i <=S ; i++)
            cin >> s[i];
        for(int j = 1 ; j<=D ; j++)
            cin >>e[j];
        floyd();
        int  ans = MAXN;
        for(int i = 1; i <=S ; i++)
            for(int j = 1; j <= D ; j++)
                if(map[s[i]][e[j]] < ans)
                    ans = map[s[i]][e[j]] ;

        cout << ans << endl;
    }

    return 0;
}

还有一种标准算法:
for(int k = 1; k <= maxx ; k++)
for(int i = 1; i <= maxx; i++)
for(int j = 1; j <= maxx; j++)
if(i!=j && i!=k && j!=k)
map[i][j] = min(map[i][j], map[i][k]+map[k][j]);
时间: 2024-10-26 19:54:46

floyd算法--一个人的旅行的相关文章

ACM: POJ 3660 Cow Contest - Floyd算法

链接 Cow Contest Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Description N (1 ≤ N ≤ 100) cows, conveniently numbered 1..N, are participating in a programming contest. As we all know, some cows code better than others. Eac

最短路径Dijkstra算法和Floyd算法整理、

转载自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最短路径—Dijkstra算法和Floyd算法 Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹

最短路径——Floyd算法

如何求一张图中任意两顶点之间的最短路径长度,这里写一种最简单的算法——Floyd算法: 1 #include<stdio.h> 2 3 #define inf 9999 4 5 int main() 6 { 7 int e[10][10]; //用邻接矩阵表示图 8 printf("请输入顶点和边的数目:"); 9 int n,m; 10 scanf("%d%d",&n,&m); 11 for(int i=0;i<n;i++) 12

HDOJ 1217 Arbitrage(拟最短路,floyd算法)

Arbitrage Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5679    Accepted Submission(s): 2630 Problem Description Arbitrage is the use of discrepancies in currency exchange rates to transform

44. 蛤蟆的数据结构笔记之四十四弗洛伊德Floyd算法

44. 蛤蟆的数据结构笔记之四十四弗洛伊德Floyd算法 本篇名言:"希望是厄运的忠实的姐妹. --普希金" 我们继续来看下数据结构图中的一个算法,这个算法来自图灵奖得主. 1.  Floyd算法介绍 Floyd算法又称为插点法,是一种用于寻找给定的加权图中多源点之间最短路径的算法.该算法名称以创始人之一.1978年图灵奖获得者.斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名.注意这个可不是心理学的那个弗洛伊德. 是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径

所有顶点之间的最短路径算法:Floyd算法。

Floyd算法的基本思想是:设集合S的初始状态为空,然后依次向集合S中加入顶点 0,1,...,n-1,每次加入一个顶点,用二维数组d保存各条最短路径的长度,其中d[i][j]存放的是顶点i到顶点j的最短路径的长度. 详细的说明: Floyd算法中最重要的办法为二维数组d[i][j],d[i][j]为从i到j中间只经过S中的顶点的.所有可能的路径中的最短路径的长度.如果从i到j通过S中的节点无法联通,则设置d[i][j]为正无穷.可以称d[i][j]存放的是从i到j的 当前最短路径 的长度.而随

最短路径之Floyd算法

Floyd算法又称弗洛伊德算法,也叫做Floyd's algorithm,Roy–Warshall algorithm,Roy–Floyd algorithm, WFI algorithm. Floyd算法是一种在有权图中(有确定的非负的权值,不能存在环路)查找最短路径的算法.该算法的一次简单执行可以找出任意结点之间的最短路径(尽管它没有返回路径的具体信息). 思想: Floyd算法通过比较图中任意两点间所有可能存在的路径长度得到最短路径长度. 我们定义一个函数shortestPath(i,j,

hihoCoder#1089 最短路径&#183;二:Floyd算法

原题地址 感觉Floyd算法比Dijkstra还要简单.. 唯一需要注意的是,初始的距离默认值不要设过大,否则溢出就不好了,根据题意,只要大于10^3即可 代码: 1 #include <iostream> 2 #include <cstring> 3 4 using namespace std; 5 6 #define MAX_POINT 1024 7 #define MAX_EDGE 16384 8 9 int N, M; 10 int d[MAX_POINT][MAX_POI

hihocoder1089 Floyd算法

题目链接:http://hihocoder.com/problemset/problem/1089 算法描述: floyd算法是求解图中任意两点最短路的经典算法,复杂度为O(n^3).虽然我们完全可以用n次dijkstra算法来求任意两点的最短路,复杂度也是O(N^3),但如果有一个算法只需要5行代码就可以完成我们想做的事情,我们有什么理由不用它?! floyd算法主要用了动态规划的思想: 设d[i][j]表示i到j的最短路径的长度, 那么我们可以这样来求解d[i][j]: (1)首先,i到j的