蓝桥杯-大臣的旅费java篇

探讨了蓝桥杯竞赛中大臣的旅费问题,利用图论中的无环图特性,设计算法寻找两个城市间最大旅费路径。通过两次深度优先搜索算法优化计算效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

蓝桥杯-大臣的旅费

资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
很久以前,T王国空前繁荣。为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市。

为节省经费,T国的大臣们经过思考,制定了一套优秀的修建方案,使得任何一个大城市都能从首都直接或者通过其他大城市间接到达。同时,如果不重复经过大城市,从首都到达每个大城市的方案都是唯一的。

J是T国重要大臣,他巡查于各大城市之间,体察民情。所以,从一个城市马不停蹄地到另一个城市成了J最常做的事情。他有一个钱袋,用于存放往来城市间的路费。

聪明的J发现,如果不在某个城市停下来修整,在连续行进过程中,他所花的路费与他已走过的距离有关,在走第x千米到第x+1千米这一千米中(x是整数),他花费的路费是x+10这么多。也就是说走1千米花费11,走2千米要花费23。

J大臣想知道:他从某一个城市出发,中间不休息,到达另一个城市,所有可能花费的路费中最多是多少呢?

输入格式
输入的第一行包含一个整数n,表示包括首都在内的T王国的城市数

城市从1开始依次编号,1号城市为首都。

接下来n-1行,描述T国的高速路(T国的高速路一定是n-1条)

每行三个整数Pi, Qi, Di,表示城市Pi和城市Qi之间有一条高速路,长度为Di千米。

输出格式
输出一个整数,表示大臣J最多花费的路费是多少。
样例输入1
5
1 2 2
1 3 1
2 4 5
2 5 4
样例输出1
135
输出格式
大臣J从城市4到城市5要花费135的路费。

题目理解:
在这里插入图片描述

从题目的意思来看,就是一个无环图,某个城市到达另一个城市的距离最大即是答案。
例如A-B城有4千米
各段的路费
1千米的路费:1+10=11
2千米的路费:2+10=12
3千米的路费:3+10=13
4千米的路费:4+10=14
所以4千米的路费为11+12+13+14=50
不难看出就是个等差数列,设千米为x,即公式为((x+10+11)*x)/2
所以无非就是求某城市到某城市的权重累计最大
思路1:将每个城市可以到的的城市都搜索一遍,算出最大权重,代码为下

    package com.example.niuke.BlueBridgeCup.Test;

import java.util.*;

public class 大臣的旅费 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();//城市个数
        HashMap<Integer, Integer>[] map = new HashMap[n+1];//连接点<城市,权重>;
        for (int i = 0; i < n - 1; i++) {
            int cur = scanner.nextInt();//当前的城市
            if (map[cur] == null)
                map[cur] = new HashMap<Integer, Integer>();
            int connect = scanner.nextInt();//连接的城市
            if(map[connect]==null)
                map[connect] = new HashMap<Integer, Integer>();//被连接的城市
            int v = scanner.nextInt();//权重
            //相互设置连接
            map[cur].put(connect, v);
            map[connect].put(cur,v);
        }
        //记录当期的城市是否处理过
        boolean[] flag=new boolean[n+1];
        //将每个城市都作为出发点,进行dfs,求出最大res
        for (int i = 1; i < map.length; i++) {
            dfs(map,i,0,flag);
        }
        System.out.println(res);
    }

    /**
     * @param map
     * @param start:当前城市的位置
     * @param v:累计的权重
     */
    static int res = Integer.MIN_VALUE;
    public static void dfs(HashMap<Integer, Integer>[] map, int start, int v,boolean[] flag) {
        if (start >= map.length||flag[start]) return;//剪枝
        //记录最大的价格
        if(res<((v + 21) * v) / 2){
            res=((v + 21) * v) / 2;
        }
        if(map[start]==null)return;
        HashMap<Integer, Integer> hashMap = map[start];
        Set<Integer> set =hashMap.keySet();
        flag[start]=true;
        for (Integer integer : set) {//与当前start城相连接的城市
            dfs(map, integer,v+hashMap.get(integer),flag);
        }
        //回溯之后
        flag[start]=false;
    }
}

在这里插入图片描述
在这里插入图片描述
当然暴力是可以算出来,但是非常吃时间,所以我们只需要在遍历的次数上减少一些城市就可以

思路2:我们将城市1首都将城市分割为两半,只需要找到 从首都出发,权重最高的那个城市,城市c找到后,搜索c的最高权重,因为从首都出发,最高的权重是c,那么在加上另一半,求出来的权重也就是最大
在这里插入图片描述

package com.example.niuke.BlueBridgeCup.Test;

import java.util.*;

public class 大臣的旅费 {
    public static void main(String[] args) {
        /**
         * 5
         * 1 2 2
         * 1 3 1
         * 2 4 5
         * 2 5 4
         */
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();//城市个数
        HashMap<Integer, Integer>[] map = new HashMap[n+1];//连接点<城市,路程>;//没有0
        for (int i = 0; i < n - 1; i++) {
            int cur = scanner.nextInt();//当前的城市
            if (map[cur] == null)
                map[cur] = new HashMap<Integer, Integer>();
            int connect = scanner.nextInt();//连接的城市
            if(map[connect]==null)
                map[connect] = new HashMap<Integer, Integer>();//被连接的城市
            int v = scanner.nextInt();//权重
            //相互设置
            map[cur].put(connect, v);
            map[connect].put(cur,v);
        }
//        System.out.println(Arrays.toString(map));
        //将每个节点遍历一遍,太消耗内存和时间
        boolean[] flag=new boolean[n+1];
//        for (int i = 1; i < map.length; i++) {
//            dfs(map,i,0,flag);
//        }
        dfs(map,1,0,flag);//第一次遍历,找到从首都出发,权重最高的城市
        dfs(map,city,0,flag);//从权重最高的城市出发,最后的res就是答案
        System.out.println(res);
    }

    /**
     * @param map
     * @param start:起始位置
     * @param v:累计的权重
     */
    static int res = Integer.MIN_VALUE;
    static int city=-1;//记录最大的城市
    public static void dfs(HashMap<Integer, Integer>[] map, int start, int v,boolean[] flag) {
        if (start >= map.length||flag[start]) return;
        //记录最大的价格
        if(res<((v + 21) * v) / 2){
            res=((v + 21) * v) / 2;
            city=start;//记录当前权重最大的城市
        }
        if(map[start]==null)return;
        HashMap<Integer, Integer> hashMap = map[start];
        Set<Integer> set =hashMap.keySet();
        flag[start]=true;
        for (Integer integer : set) {
            dfs(map, integer,v+hashMap.get(integer),flag);
        }
        flag[start]=false;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值