赞
踩
容易想到,从0点出发DFS,期间维护已经走过的距离(时间)和途径点的权值之和,若访问到0点则更新答案,若下一步的距离与已走过的距离和超出了maxTime,则不能向下继续DFS
注意的是,每个点的权值只会计算一次,可以使用一个boolean数组 vis[ ] 来记录该点的权值是否已经计算过
另一种方法是,每当第一次到达一个点并获得权值后,将它的权值修改为0,若后续又一次访问到该点,加0不会影响最终结果,省去vis数组的操作
超时,通过样例59 / 62
class Solution { int res; public void dfs(int x, int[] values, int[][] map, int maxTime, int time, int sum){ if(x == 0){ res = Math.max(res, sum); } int n = values.length; for(int i = 0 ; i < n; i ++){ if(map[x][i] != 0 && time + map[x][i] <= maxTime){ int val = values[i]; values[i] = 0; dfs(i, values, map, maxTime, time + map[x][i], sum + val); values[i] = val; } } return ; } public int maximalPathQuality(int[] values, int[][] edges, int maxTime) { int n = values.length; int [][] map = new int [n][n]; for(int[] e: edges){ int a = e[0]; int b = e[1]; int t = e[2]; map[a][b] = t; map[b][a] = t; } res = 0; int val = values[0]; values[0] = 0; dfs(0, values, map, maxTime, 0, val); return res; } }
注意到,当判断一个点是否可以继续深入时,可以考虑的一种剪枝方式是,向该点前进后,若剩余的时间不足以返回0点,则不必向该点DFS
该问题转换为,判断x点回到0点的距离是否超过maxTime - time,即为0点出发的最短路问题,使用Dijstra算法实现
另一方面,当图中的点较稀疏时,使用邻接矩阵遍历找边会导致时间的浪费,因此选择使用邻接表实现图的存储
class Solution { int res; public void dfs(int x, int[] values, List<int[]>[] map, int maxTime, int time, int sum, int[] dis){ if(x == 0){ res = Math.max(res, sum); } int n = values.length; for(int arr[] : map[x]){ int y = arr[0]; int t = arr[1]; // 求和时增加dis,若不足返回0点则不必DFS if(time + t + dis[y] <= maxTime){ int val = values[y]; values[y] = 0; dfs(y, values, map, maxTime, time + t, sum + val, dis); values[y] = val; } } return ; } public int maximalPathQuality(int[] values, int[][] edges, int maxTime) { int n = values.length; // 邻接表 map[x]为x发出的边的集合List,List中的每个int[],int[0]为终点,int[1]为距离 List<int[]>[] map = new ArrayList[n]; for(int i = 0 ; i < n; i ++){ map[i] = new ArrayList<int[]>(); } for(int[] e: edges){ int a = e[0]; int b = e[1]; int t = e[2]; map[a].add(new int[]{b, t}); map[b].add(new int[]{a, t}); } // dijstra int inf = Integer.MAX_VALUE; int dis[] = new int [n]; Arrays.fill(dis, inf); for(int [] arr: map[0]){ int y = arr[0]; int t = arr[1]; dis[y] = t; } boolean vis[] = new boolean[n]; vis[0] = true; while(true){ int min = Integer.MAX_VALUE; int index = -1; for(int i = 0 ; i < n; i ++){ if(!vis[i] && dis[i] < min){ min = dis[i]; index = i; } } if(index == -1) break; vis[index] = true; // 遍历index点发出的边 for (int[] arr : map[index]) { int v = arr[0]; int t = arr[1]; if (!vis[v] && dis[index] + t < dis[v]) { dis[v] = dis[index] + t; } } } // DFS res = 0; int val = values[0]; values[0] = 0; dfs(0, values, map, maxTime, 0, val, dis); return res; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。