TSP

public class TSP {

    private double[][] dArray; // 距离矩阵
    private int length; // 距离矩阵的长度

    public double[][] getdArray() {
        return dArray;
    }

    public int getLength() {
        return length;
    }

    public TSP(double[][] dArray) {
        if (this.check(dArray)) {
            this.dArray = dArray;
            this.length = dArray.length;
        }
    }

    private void dynamic() {
        double[][] D = this.dArray;// 原图的邻接矩阵
        int n = this.length;
        if (this.check(D)) {
            int m = (int) Math.pow(2, n - 1);// 列长度,每行有2的n-1次方列
            double[][] F = new double[n][m];// 存储阶段最优值,指标
            int[][] M = new int[n][m];// 存放阶段最优策略
            // 初始化F[][]和M[][]
            for (int j = 0; j < m; j++) {
                for (int i = 0; i < n; i++) {
                    F[i][j] = -1;
                    M[i][j] = -1;
                }
            }
            // 给F的第0列赋初值
            for (int i = 0; i < n; i++) {
                F[i][0] = D[i][0];
            }
            // 遍历并填表,除最后一列外,i:行,j:列
            double min = 0;
            for (int j = 1; j < m - 1; j++) {
                for (int i = 1; i < n; i++) {
                    if (((int) Math.pow(2, i - 1) & j) == 0) {
                        // 城市i不在j所代表的二进制集合中,可以填表
                        min = 0;
                        for (int k = 1; k < n; k++) {
                            if (((int) Math.pow(2, k - 1) & j) != 0) {
// 对于j集合中所有的k城市,都要存储,j-(int)Math.pow(2, k-1)表示去掉k城市节点后剩下的集合
                                double temp = D[i][k] + F[k][j - (int) Math.pow(2, k - 1)];
                                if (min == 0) {
                                    //第一次循环,直接给最小值赋初值
                                    min = temp;
                                    F[i][j] = min;// 保存阶段最优值
                                    M[i][j] = k;// 保存最优决策
                                }else {
                                    if (temp < min) {
                                        //取小
                                        min = temp;
                                        F[i][j] = min;// 保存阶段最优值
                                        M[i][j] = k;// 保存最优决策
                                    }
                                }
                            }
                        }
                    }
                }
            }
            // 最后一列,即总最优值的计算,且只有第一行有值,且为最优
            min = 0;
            for (int k = 1; k < n; k++) {
                // 二进制全1,表示集合{1,2,3,4,5},从中去掉k结点即将k对应的二进制位置0
                double temp = D[0][k] + F[k][m-1-(int) Math.pow(2, k - 1)];
                if (min == 0) {
                    //第一次循环,直接给最小值赋初值
                    min = temp;
                    F[0][m-1] = min;// 总最优解
                    M[0][m-1] = k;
                }else {
                    if (temp < min) {
                        //取小
                        min = temp;
                        F[0][m-1] = min;// 总最优解
                        M[0][m-1] = k;
                    }
                }
            }
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < n; j++) {
                    System.out.print(F[j][i]+",");
                }
                System.out.println();
            }
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < n; j++) {
                    System.out.print(M[j][i]+",");
                }
                System.out.println();
            }
            //输出结果,回溯查表M
            System.out.println("最短距离为:"+ F[0][m-1]);
            System.out.print("最短路径顺序为:"+"0");
            for (int j = m-1,i = 0; j > 0; ) {
                i = M[i][j];//下一步去往哪个城市结点
                j = j-(int)Math.pow(2, i-1);//从j中去掉i节点
                System.out.print("-->"+i);
            }
            System.out.println("-->0");
        }
    }

    private boolean check(double[][] dArray) {
        // 城市少于三个
        if (dArray.length < 3) {
            System.out.println("错误信息:距离矩阵长度过小");
            return false;
        }
        // 不是方阵
        for (int i = 0; i < dArray.length; i++) {
            if (dArray.length != dArray[i].length) {
                System.out.println("错误信息:距离数组长度不合法");
                return false;
            }
        }
        for (int i = 0; i < dArray.length; i++) {
            if (!oneZero(dArray[i], i)) {
                System.out.println("错误信息:城市间距离设置不合法");
                return false;
            }
        }
        return true;
    }

    // 对于一个doulbe类型的数组, 当且仅有对角元素为0
    private boolean oneZero(double[] dArray, int i) {
        int numOfZero = 0;
        for (double d : dArray) {
            if (d == 0.0) {
                numOfZero++;
            }
        }
        if (numOfZero == 1 && (dArray[i] == 0)) {
            return true;
        } else {
            return false;
        }
    }

     //主函数
    public static void main(String[] args) {
        double[][] D = { // 各个节点之间路径长度的二维数组
                { 0, 10, 20, 30, 40, 50 }, 
                { 12, 0, 18, 30, 25, 21 }, 
                { 23, 9, 0, 5, 10, 15 }, 
                { 34, 32, 4, 0, 8, 16 }, 
                { 45, 27, 11, 10, 0, 18 }, 
                { 56, 22, 16, 20, 12, 0 }
        };
        long start = System.currentTimeMillis();
        TSP ff = new TSP(D);
        ff.dynamic();
        long end = System.currentTimeMillis();
        long between = end - start;
        System.out.println("java环境下用动态规划思想求解TSP问题的运行时间为:"+between+"ms");
    }
}
全部评论

相关推荐

SadnessAlex:跟三十五岁原则一样,人太多给这些***惯坏了
点赞 评论 收藏
分享
04-30 21:35
已编辑
长安大学 C++
晓沐咕咕咕:评论区没被女朋友好好对待过的计小将可真多。觉得可惜可以理解,毕竟一线大厂sp。但是骂楼主糊涂的大可不必,说什么会被社会毒打更是丢人。女朋友体制内生活有保障,读研女朋友还供着,都准备订婚了人家两情相悦,二线本地以后两口子日子美滋滋,哪轮到你一个一线城市房子都买不起的996清高计小将在这说人家傻😅
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务