蓝桥杯——基础练习——逗志芃的暴走

问题描述

  逗志芃是有妹子的现充,但是有时候妹子就是烦恼。因为逗志芃太逗了,所以这段时间妹子对逗志芃发动了技能无理取闹,妹子要去玩很多的景点。由于逗志芃之前抽机花费了太多的时间,不久以后又要微积分考试了,所以现在被妹子搞成暴走状态了。但是妹子永远是上帝,所以逗志芃只能带妹子出去玩,不过为了节约时间,他希望找到一条花费时间最少的一次性游览线路。

输入格式

  第一行1个数n,表示逗志芃所在的城市有多少个景点,接下来是一个n*n的矩阵。a(i,j)表示i号景点到j号景点的路上花费的时间是多少。
  接下来是一个数m,表示逗志芃妹子要去去的景点数目。由于妹子在无理取闹,所以可能会有重复的景点,不过只要去一次就可以了。接下来是m个数,就是妹子要去的景点编号。

输出格式

  一个数,最少的花费时间。

样例输入

3
0 1 2
1 0 3
2 3 0
3
2 3 1

样例输出

3

数据规模和约定

  0<n<=30,0<m<=20,时间<=1000000

简单的floyed算法+dfs算法

package com.study.蓝桥杯.算法训练;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Scanner;

/**
 * @author sjn
 * @date 2022-2-23
 */

/*
问题描述
  逗志芃是有妹子的现充,但是有时候妹子就是烦恼。因为逗志芃太逗了,所以这段时间妹子对逗志芃发动了技能无理取闹,
    妹子要去玩很多的景点。由于逗志芃之前抽机花费了太多的时间,不久以后又要微积分考试了,所以现在被妹子搞成暴走状态了。
    但是妹子永远是上帝,所以逗志芃只能带妹子出去玩,不过为了节约时间,他希望找到一条花费时间最少的一次性游览线路。
输入格式
  第一行1个数n,表示逗志芃所在的城市有多少个景点,接下来是一个n*n的矩阵。a(i,j)表示i号景点到j号景点的路上花费的时间是多少。
  接下来是一个数m,表示逗志芃妹子要去去的景点数目。由于妹子在无理取闹,所以可能会有重复的景点,不过只要去一次就可以了。
    接下来是m个数,就是妹子要去的景点编号。
输出格式
  一个数,最少的花费时间。
 */
public class ALGO_954逗志芃的暴走 {
    //全局变量res用来保存最短路径
    static int res = Integer.MAX_VALUE;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[][] arr = new int[n + 1][n + 1];

        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                arr[i][j] = sc.nextInt();
            }
        }

        int m = sc.nextInt();
        HashSet<Integer> hs = new HashSet<>();//用set集合降重
        for (int i = 0; i < m; i++) {
            hs.add(sc.nextInt());
        }

        int[] spot = hs.stream().mapToInt(Integer::valueOf).toArray();

        //使用floyed算出两个景点之前的最短路径
        floyed(arr);

        dfs(arr, spot, new boolean[hs.size()], new ArrayList<Integer>());
        System.out.println(res);
    }

    //floyed算法,算出两景点之间的最短路径
    public static void floyed(int[][] arr) {
        int n = arr.length - 1;
        for (int k = 1; k <= n; k++) {//k表示的是跳板景点,先从i景点到k景点再从k景点到j景点
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= n; j++) {
                    arr[i][j] = Math.min(arr[i][j], arr[i][k] + arr[k][j]);
                }
            }
        }
    }

    /**
     * @param arr  保存两景点之间最短距离的数组
     * @param spot 妹子想去的城市
     * @param vis  第i个城市是否被访问
     * @param rank 存储景点的全排列
     */
    public static void dfs(int[][] arr, int[] spot, boolean[] vis, ArrayList<Integer> rank) {
        if (rank.size() == spot.length) {//递归出口
            int sum = 0;
            for (int i = 0; i < rank.size() - 1; i++) {
                sum += arr[rank.get(i)][rank.get(i + 1)];
            }

            res = Math.min(sum, res);
            return;
        }

        for (int i = 0; i < spot.length; i++) {
            int c = spot[i];
            if (!vis[i]) {
                rank.add(c);
                vis[i] = true;//true表示被访问
                dfs(arr, spot, vis, rank);
                //回溯
                rank.remove(rank.size() - 1);
                vis[i] = false;
            }
        }
    }
}

 

上一篇:web前端学习笔记-2(随笔)


下一篇:【JavaScript】Web Worker