蓝桥杯-大臣的旅费
资源限制
时间限制: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;
}
}