所有点之间的最短路径问题,弗洛伊德沃尔索尔

时间:2011-03-02 02:49:51

标签: c shortest-path dijkstra

  

先生。罗恩打算去徒步旅行   巴黎但是,因为他是一个   小懒,他想拿走   通过所有人的最短路径   他想去的地方。他计划   坐公共汽车到第一个地方   另一个从最后一个地方回来,   所以他可以自由选择首发   和结束的地方。你能帮助他吗?

     

输入

     

第一行输入包含   参观人数(n)。然后,   在以下n行中,您会找到   每个地方的坐标。   这是一个例子:

     
    

3

         

132 73

         

49 86

         

72 111

  
     

输出

     

对于每个测试用例,您的程序   应输出一行包含   罗恩先生必须达到的最小距离   走路去参观假设的所有地方   从一个地方到步行距离   另一个是欧几里德距离。该   算法应输出一个数字   正好用3的定点表示法   小数点右边的数字   点,没有领先的空间。有   最多12个地方参观。实施例

     

示例输入:

     
    

3

         

132 73

         

49 86

         

72 111

  
     

示例输出:

     
    

104.992

  

我一直在研究这个代码,我的作业,但我不能让它工作,我开始想知道这是否是最好的方法..

问题是floyd-warshall函数,它在float **路径结构上什么也没做。不知道为什么..在floydwarshall(path,n,next)之前和之后路径是相同的;

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <float.h>

/*Implementing of http://en.wikipedia.org/wiki/Floyd–Warshall_algorithm*/


struct point {
    float x;
    float y;
};


float cost(struct point* a, struct point* b) {

    return sqrt(pow((*a).x - (*b).x, 2) + pow((*a).y - (*b).y, 2));

}


float** f2dmalloc(int n, int m){

    int i;
    float **ptr;

    ptr = malloc(n * sizeof(float *));
    for (i = 0; i < n; i++) {
        ptr[i] = calloc(m, sizeof(float));
    }

    return ptr;

}



void floydwarshall(float **path, int n, float ** next){
    int i, j, k;
    float a, b;
    for (k = 0; k < n; k++) {
        for (i = 0; i < n; i++) {
            for (j = 0; j < n; j++) {
                a = path[i][j];
                b = path[i][k] + path[k][j];
                path[i][j] = ((a) < (b) ? a : b);
                next[i][j] = k;

            }
        }
    }

}

int main (int argc, const char* argv[])
{



    int i;
    int j;
    int n;

    float temp;
    float mininum;

    scanf("%d", &n);

    /*
    A 2-dimensional matrix. At each step in the algorithm, path[i][j] is the shortest path
    from i to j using intermediate vertices (1..k−1).  Each path[i][j] is initialized to
    cost(i,j).
    */
    float ** path;
    float ** next;
    struct point* points;

    path = f2dmalloc(n, n);
    next = f2dmalloc(n, n);

    points = malloc(n * sizeof(struct point));

    for (i = 0; i < n; i++){
        scanf("%f %f", &(points[i].x), &(points[i].y));
    }


    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            path[i][j] = cost(&points[i], &points[j]);
        }
    }


    temp = 0;
    for (i = 0; i < n; i++) {
        mininum = FLT_MAX;
        for (j = 0; j < n; j++) {
            printf("%.3f\t", path[i][j]);
            if (path[i][j] < mininum && path[i][j] != 0){
                mininum = path[i][j];
            }

        }
        printf("\tminimum - %.3f\n", mininum);
        temp += mininum;
    }

    floydwarshall(path, n, next);


    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            printf("%.3f\t", next[i][j]);

        }
        printf("\n");
    }

    /*
    temp = 0;
    for (i = 0; i < n; i++) {
        mininum = FLT_MAX;
        for (j = 0; j < n; j++) {
            printf("%.3f\t", path[i][j]);
            if (path[i][j] < mininum && path[i][j] != 0){
                mininum = path[i][j];
            }

        }
            printf("\tminimum - %.3f\n", mininum);
        temp += mininum;
    }

    printf("%.3f\n", temp);

     */

    return 0;
}

1 个答案:

答案 0 :(得分:3)

Floyd-Warshall解决了这个问题:对于每对点,找到加入它们的最短路径。 (它需要加入这两点。它不需要做任何其他事情。如果产生更短的路径,它只会访问其他点。)

在目前的情况下,由于你总是可以直接从任何一点到另一个点,最短的路径始终是直接的路径:只需从A到B.(这就是为什么呼叫floydwarshall不改变一切。)

但是你试图解决的问题似乎是旅行商问题:找到一条路径 all 你的积分并且尽可能短。

这些是完全不同的问题,你需要做一些完全不同的事情来解决你被要求解决的问题。