动态规划求解TSP问题

import java.awt.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

public class Main {
    public static void main(String[] args) {
        int c[][] = {
                {0, 3, 6, 7},
                {5, 0, 2, 3},
                {6, 4, 0, 2},
                {3, 7, 5, 0}
        };

        Node node = new Node(c.length);

        // 初始化状态
        for (int i = 1; i < c.length; i++) {
            node.list[i].put(new HashSet<>(), c[i][0]);
        }

        // 迭代,次数为n - 2次,n为各顶点数
        for (int d = 2; d < c.length; d++) {
            Node node1 = new Node(c.length);
            // i作为入度顶点
            for (int i = 1; i < c.length; i++) {
                HashMap<Set<Integer>, Integer> item = node.list[i];
                
                if (item.size() == 0) continue;

                Set<Set<Integer>> sets = item.keySet();
                
                // j为出发点, j -> i
                for (int j = 1; j < c.length; j++) {
                    // j -> i 如果无路可走就寻找下一个顶点
                    if (c[j][i] == 0) continue;

                    int min = Integer.MAX_VALUE;
                    Set<Integer> set1 = null;

                    // 寻找保存j -> i时,然后 ->... -> 0的最短路径
                    for (Set<Integer> set : sets) {
                        // 如果j已经在已走过的顶点集里则跳过
                        if (set.contains(j)) continue;
                        int res = c[j][i] + item.get(set);
                        if (min > res) {
                            min = res;
                            set1 = set;
                        }
                    }

                    HashSet<Integer> set2 = new HashSet<>();
                    for (Integer integer : set1) {
                        set2.add(integer);
                    }
                    set2.add(i);

                    HashMap<Set<Integer>, Integer> hm = node1.list[j];
                    
                    // 保存j -> i .... -> 0 的最短路径长度,如果已有走过的该顶点集,则取最小值
                    if (hm.containsKey(set2)) {
                        hm.put(set2, Math.min(hm.get(set2), min));
                    } else {
                        hm.put(set2, min);
                    }

                }
            }

            node = node1;
        }

        // 最后求出0 -> 各个点的最小值
        int min = Integer.MAX_VALUE;
        for (int i = 1; i < c.length; i++) {
            HashMap<Set<Integer>, Integer> item = node.list[i];
            if (item.size() == 0) continue;

            Set<Set<Integer>> sets = item.keySet();

            if (c[0][i] == 0) continue;
            
            for (Set<Integer> set : sets) {
                int res = c[0][i] + item.get(set);
                if (min > res) {
                    min = res;
                }
            }
        }

        System.out.println(min);


    }
}

class Node {
    HashMap<Set<Integer>, Integer>[] list;

    public Node(int n) {
        this.list = new HashMap[n];
        for (int i = 0; i < n; i++) {
            list[i] = new HashMap();
        }
    }
}

时间复杂度相对于暴力的O(N!) 下降到 O(2^n)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值