【实验】旅行路线规划问题

实验要求

  1. 实验目的:加深图的汉密尔顿路及最短路径的理解与应用
  2. 实验内容:搜索某旅游城市地图(至少包含10个景点),随机选取出发地点,基于图论理论建立模型,给出合理的旅行路线。要求考虑时间、成本等因素。
  3. 实验原理和方法:
    (1) 不多于3名同学一组,选择某一旅游城市为研究对象,考察该城市至少10个景点在地图中的位置,根据景点间的路径绘制路线图。
    (2) 考虑两个景点间的距离、交通工具等因素,设置路线权重。
    (3) 随机从任意一点出发,基于图论理论建立模型,给出合理的旅行路线。
  4. 参考案例
    该问题是一个典型的旅行商问题,通常用加权图表示。如果已知顶点u和顶点v的距离是r,连接u和v这两点权重就是r。图中一个圈C的权指的是C中所有边的权重之和。为了解决旅行商问题,我们需要确定加权图中哈密尔顿图的最小权值。以推销员在城市间巡回旅行为例,介绍该问题的求解。
    问题:一个推销员计划在一些城市间巡回旅行,城市间的距离如图所示的加权图G,那么他这次旅行的最小距离是多少?
    在这里插入图片描述
    解答:因为图G是5阶图,因此G中有(5-1)!/2=12个哈密尔顿圈,每个圈及其权重列表如下:
哈密尔顿圈 圈的权重
S1=(C1,C2,C3,C4,C5,C1) 7+10+8+6+12=43
S2=(C1,C2,C3,C5,C4,C1) 7+10+4+6+9=36
S3 = (C1,C2,C4,C3,C5,C1) 44
S4=(C1,C2,C4,C5,C3,C1) 41
S5=(C1,C2,C5,C3,C4,C1) 42
S6=(C1,C2,C5,C4,C3,C1) 46
S7=(C1,C3,C2,C4,C5,C1) 52
S8=(C1,C3,C2,C5,C4,C1) 50
S9=(C1,C3,C4,C2,C5,C1) 58
S10=(C1,C3,C5,C2,C4,C1) 51
S11=(C1,C4,C2,C3,C5,C1) 48
S12=(C1,C4,C3,C2,C5,C1) 53
因此,从表中可读出哈密尔顿圈的最小权重为36.为了获得此权重,G中的点按照C1,C2,C3,C5,C4,C1或者C1,C4,C5,C3,C2,C1的顺序访问。
  1. 实验过程:

  2. 遇到的问题和解决方案:

数据在这里插入图片描述

图的表示

在这里插入图片描述

输入数据

//运行时将下面这些信息直接复制到控制台, 回车即可:(本行不要录入)
10
北京
天津
上海
重庆
呼市
乌鲁木齐
拉萨
银川
南宁
哈尔滨
125
1239
3026
480
3300
3736
1192
2373
1230
1150
1954
604
3330
3740
1316
2389
1207
1945
1717
3929
4157
2092
1892
2342
1847
3202
2457
1570
993
3156
2825
3260
716
2657
1710
2668
2111
4279
4531
2547
3431
4967
2673
2422
3592

代码

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

class Point{
    int selected;
    int id;
    String name;
    Point(String name){
        this.name = name;
    }
}

class Edge{
    Point[] points = new Point[2];
    int value;
    Edge(int value){
        this.value = value;
    }
}

public class Hamilton {

    private static Edge[] allEdges;

    public static void main(String[] args){

        Scanner sc = new Scanner(System.in);
        System.out.println("Please enter the number of the city: ");
        int n = sc.nextInt();
        int m = (n - 1) * n / 2;

        Point[] allPoints = new Point[n];
        allEdges = new Edge[m];

        for (int i = 0; i < n; i++) {
            System.out.printf("Please enter the name of the city %d: ", i+1);
            allPoints[i] = new Point(sc.next());
            allPoints[i].id = i;
        }

        int count = 0;
        for(int i = 0; i < n; i ++){
            for (int j = i + 1; j < n; j++) {
                if(i != j){
                    System.out.printf("PLease enter the value between %s and %s: ", allPoints[i].name, allPoints[j].name);
                    int v = sc.nextInt();
                    allEdges[count] = new Edge(v);
                    allEdges[count].points[0] = allPoints[i];
                    allEdges[count].points[1] = allPoints[j];
                    count ++;
                }
            }
        }

        System.out.println();
        
        List<Point> rst = new ArrayList<>();

        Point start = allPoints[0];
        rst.add(start);
        start.selected = 1;
        int c = 0;

        while(c < n -1){
            Point next = getMinPoint(start, allPoints);
            rst.add(next);
            next.selected = 1;
            start = next;
            c ++;
        }

        rst.add(allPoints[0]);

        for (int i = 0; i < rst.size(); i++) {
            if(i == rst.size()-1){
                System.out.print(rst.get(i).name);
            }else{
                System.out.print(rst.get(i).name + "--->");
            }
        }
    }

    private static int getValueOfPoints(Point p1, Point p2){
        for (Edge edge : allEdges) {
            if((edge.points[0] == p1 && edge.points[1] == p2) || (edge.points[1] == p1 && edge.points[0] == p2)){
                return edge.value;
            }
        }
        return 0;
    }

    private static Point getMinPoint(Point p1, Point[] ps){
        int[] values = new int[ps.length];
        for (int i = 0; i < ps.length; i++) {
            if(ps[i].selected == 0){
                values[i] = getValueOfPoints(p1, ps[i]);
            }else{
                values[i] = 99999;
            }
        }
        int min = values[0];
        int index = 0;
        for (int i = 0; i < values.length; i++) {
            if(values[i] <= min){
                min = values[i];
                index = i;
            }
        }
        return ps[index];
    }
    
}

高分建议

懂的人都知道这是什么,不懂的就不懂吧,不懂也别问。

他们会给你参考书名称的,你根本借不到。其中有一本我看过,没什么解决方案,这份指导书里面的样例讲解的已经很详细了(就是书里的内容)。

代码呢,因为是很久之前写的嘛,所以肯定不够好。

建议想得高分的话,把问题好好弄一弄。我们当时考虑的是最简单的情况,你们可以多考虑一些因素。

组队要选一个算法不错的人,最好是有点ACM底子,能搞事情。

你甚至可以尝试模拟的退火算法那些神奇的东西。

我当时见有人打暴力把Java爆了栈,还见过Python跑了一个小时的情况,所以你还是不要写那种暴力算法,否则分数高不了。

十个节点有 9!/2=362880 种情况,后面可能允许你降低结点数量。但你要记住,降低复杂度就是在自己折分。

发布了726 篇原创文章 · 获赞 1550 · 访问量 72万+

猜你喜欢

转载自blog.csdn.net/weixin_43896318/article/details/104938780
今日推荐