网易的游历魔法王国,考虑往回走的情况。暴力深搜代码。
import java.util.Scanner; /** * 网易游历魔法王国问题,考虑往回走的情况。 * 此处使用深度优先搜索,抛砖引玉,希望有大神给最优算法代码。 */ public class Test10 { static int sum = 0; public static void main(String[] args) { Scanner in = new Scanner(System.in); int N = in.nextInt(); int L = in.nextInt(); in.nextLine(); int[] parent = new int[N - 1]; for (int i = 0; i < N - 1; i++) { parent[i] = in.nextInt(); } in.nextLine(); sum = 0; int[] mark = new int[N]; // 用于表示是否被访问过 try { work1(parent, 0, 0, -1, mark, L + 1, N); } finally { System.out.println(sum); } in.close(); } /** * 深度优先搜索,可以走重复的路径,直到步数用完。 * * @param parent 输入的数组,表示相邻边 * @param temp 暂存游历的城市数目 * @param id 表示当前游历到的城市 * @param preid 表示前面一个游历的城市 * @param mark 标志数组,记录游历了哪些城市 * @param L 表示剩余的步数 * @param N 表示总的城市个数 * @return 返回剩余步数 */ public static int work1(int[] parent, int temp, int id, int preid, int[] mark, int L, int N) { // 第0个节点假设它的前一个节点为-1; if (id == -1) return L; L--; // 游历步数-1 // 如果城市没有被访问过,则游历城市数+1; if (mark[id] == 0 && ++temp > sum) sum = temp; mark[id]++; // 标记已经访问此城市。 // 如果没有游历次数了,则退出。 if (L == 0) { mark[id]--; // 回溯; return 0; } // 如果所有的城市都游历过了,但是步数还没有用完,则应该直接退出代码,最大值即为城市个数。防止步数特别大的情况。 int count = 0; for (int i = 0; i < N; i++) { if (mark[i] == 0) { break; } count++; } if (count == N) { sum = N; new Exception(); // 用异常退出递归 } // 找出接下来可以访问的城市,继续走 for (int i = 0; i < N - 1; i++) { if (parent[i] == id && mark[i + 1] == 0) // 如果下一个城市没有被访问过,则往下走。 { int leftL = work1(parent, temp, i + 1, id, mark, L, N); if (leftL > 0) // 如果一直往下走到尽头后还有剩余的步骤,则往回走。 work1(parent, temp, preid, id, mark, leftL, N); } } // 直接往回走,不往下走了,找其他支路上的没访问过的节点。 int left = work1(parent, temp, preid, id, mark, L, N); // 回溯。 mark[id]--; return left; } }
5 2
0 1 2 3
3
6 7
0 1 2 0 2 4
6