算法设计与分析: 3-15 双调旅行售货员问题

本文介绍了双调旅行售货员问题,它是欧氏旅行售货员问题的一个特殊情况,涉及从最左点到最右点再到最左点的最短路径。文章提供了问题描述,并给出了使用Java实现的解决方案,包括数据输入和输出的说明。

3-15 双调旅行售货员问题


问题描述

欧氏旅行售货员问题是对给定的平面上 n 个点确定一条连接这 n 个点的长度最短的哈密 顿回路。由于欧氏距离满足三角不等式,所以欧氏旅行售货员问题是一个特殊的具有三角不 等式性质的旅行售货员问题。它仍是一个 NP 完全问题。最短双调 TSP 回路是欧氏旅行售货 员问题的特殊情况。平面上 n 个点的双调 TSP 回路是从最左点开始,严格地由左至右直到 最右点,然后严格地由右至左直至最左点,且连接每一个点恰好一次的一条闭合回路。

给定平面上 n 个点,编程计算这 n 个点的最短双调 TSP 回路。

数据输入:
第 1 行有 1 个正整数 n,表示给定的平面上的点数。接下来的 n 行中,每行 2 个实数,分别表示点的 x 坐标和 y 坐标。


Java

import java.util.*;

class Point{
    int x;
    int y;
}

public class ShuangDiaoLvXingShouHuoYuan {

    private static List<Point> points = new ArrayList<>();
    private static double[] s,t;
    private static int n;

    public static void main(String[] args){
        Scanner input = new Scanner(System.in);

        while (true){
            points.clear();
            n = input.nextInt();
            s = new double[n+1];
            t = new double[n+1];

            for(int i=0; i<n; i++){
                Point point = new Point();
                point.x = input.nextInt();
                point.y = input.nextInt();
                points.add(point);
            }

            Collections.sort(points, xComparator);//按x坐标从小到大排序

            dynamic();

            System.out.println(String.format("%.2f", t[n]));

        }
    }

    private static Comparator<Point> xComparator = new Comparator<>() {

        @Override
        public int compare(Point c1, Point c2) {
            int result = Integer.compare(c1.x, c2.x);
            return result;
        }
    };

    /*
    t[i]: 点集{p1,p2,...,pi}的最短双调TSP回路的长度
    */
    private static void dynamic(){
        s[1] = 0;
        for(int i=2; i<=n; i++)
            s[i] = dist(i-1, i) + s[i-1];

        t[2] = 2*s[2];
        for(int i=3; i<=n; i++){
            t[i] = t[2]+s[i]-2*s[2]+dist(i,1);
            for(int j=2; j<=i-2; j++){
                double temp = t[j+1]+s[i]+s[j]-2*s[j+1]+dist(i,j);
                if(t[i] > temp)
                    t[i] = temp;
            }
        }
    }

    private static double dist(int p, int q){
        return Math.sqrt(Math.pow(points.get(p-1).x-points.get(q-1).x, 2)+Math.pow(points.get(p-1).y-points.get(q-1).y, 2));
    }
}

Input & Output

7
0 6
1 0
2 3
5 4
6 1
8 2
7 5
25.58

王晓东《计算机算法设计与分析》(第3版)P94

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值