mendge

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

题目链接

字节跳动春招研发部分编程题汇总--5

金典TSP+压缩状态DP

TSP解法介绍:浅谈旅行商问题(动态规划,回溯实现)
压缩状态DP解法请参考:旅行商问题解法

思路

上面的压缩状态DP算法经典,但是dp状态转移方程的构造理解起来微难,可以使用贪心+dfs的思路来找到花费最小的环。
即当前旅行到i点,要使得全局花费最小,则需要寻找与i最近且没有被旅行过的点去旅行(贪心)。但是可能会出现多个未旅行过的点,他们与当前i点距离相等且都是最小,需要来对这些点进行逐一搜索(dfs),全部点都遍历完成,则更新全局最小花费。(也可以理解为剪枝的dfs)
要达到全局最优还需要对出发点进行轮询指定,并不断更新全局最小花费,最终获得最优解。

代码

import java.util.LinkedList;
import java.util.Scanner;

public class Main {
    public static int[] mark = new int[21];
    public static int[][] graph = new int[21][21];
    public static int minCostSum = 0x7fffffff;
    public static int n;

    public static LinkedList<Elem> stack = new LinkedList<>();

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        n = in.nextInt();
        //接收数据
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++) {
                graph[i][j] = in.nextInt();
            }
            mark[i] = 0;
        }
        //针对每一个点作为起点都搜索一次(非常重要)
        for(int i=1;i<=n;i++){
            mark[i] = 1;
            Elem elem = new Elem(i);
            stack.addLast(elem);
            dfs();
        }
        System.out.println(minCostSum);
    }

    public static void dfs(){
        //找到一个环则更新最下环花费
        if(stack.size()==n){
            int startSite = stack.getFirst().site;
            int endSite = stack.getLast().site;
            //找到最短路径后,首尾相接构成一个环(要回到起始地)
            int cost = graph[startSite][endSite]+stack.getLast().costSum;
            minCostSum = Math.min(minCostSum,cost);
        }
        //取出前一个环
        Elem elem = stack.getLast();
        int nowSite = elem.site;
        int nowCostSum = elem.costSum;
        int minCost = 0x7fffffff;
        //找到没有旅游过的景点的最少路费
        for(int i=1;i<=n;i++)
            if(mark[i]!=1 && graph[nowSite][i] < minCost)
                minCost = graph[nowSite][i];
        //对没有旅游过且满足路费等于最小路费的景点做一次搜索
        for(int i=1;i<=n;i++){
            if(mark[i]!=1 && graph[nowSite][i] == minCost){
                Elem elem_ = new Elem(i);
                elem_.costSum = nowCostSum + minCost;
                stack.addLast(elem_);
                mark[i] = 1;
                dfs();
            }
        }
        stack.removeLast();
        mark[nowSite] = 0;
    }
}

class Elem{
    public int site;				//当前处理的Site
    public int costSum = 0;			//处理到当前Site的花费总和
    public Elem(int site){
        this.site = site;
    }
}

问题

有一组数据没过,欢迎大佬指导

输入:

18
0 8 5 9 4 3 4 5 7 9 6 5 5 8 4 5 7 5
8 0 7 4 3 3 5 4 5 7 5 4 6 6 4 5 6 5
5 7 0 4 3 2 8 6 2 5 6 3 7 4 3 3 7 6
9 4 4 0 1 3 5 9 5 3 7 3 8 9 3 4 6 6
4 3 3 1 0 7 6 8 7 5 5 4 8 6 5 6 5 4
3 3 2 3 7 0 5 4 7 9 6 5 7 3 5 8 4 4
4 5 8 5 6 5 0 7 5 6 8 6 6 2 6 9 5 4
5 4 6 9 8 4 7 0 7 4 9 7 5 4 6 9 4 3
7 5 2 5 7 7 5 7 0 6 5 8 5 6 3 4 9 3
9 7 5 3 5 9 6 4 6 0 6 9 6 7 3 4 8 3
6 5 6 7 5 6 8 9 5 6 0 6 5 7 8 6 9 2
5 4 3 3 4 5 6 7 8 9 6 0 8 5 8 6 8 1
5 6 7 8 8 7 6 5 5 6 5 8 0 3 9 3 7 1
8 6 4 9 6 3 2 4 6 7 7 5 3 0 9 4 5 2
4 4 3 3 5 5 6 6 3 3 8 8 9 9 0 8 7 9
5 5 3 4 6 8 9 9 4 4 6 6 3 4 8 0 7 10
7 6 7 6 5 4 5 4 9 8 9 8 7 5 7 7 0 11
5 5 6 6 4 4 4 3 3 3 2 1 1 2 9 10 11 0

预期输出:

54

实际输出:

55

posted on 2023-04-16 12:56  mendge01  阅读(70)  评论(0)    收藏  举报