(网易2018秋季校招笔试,最详细、易懂的解法)[编程题] 游历魔法王国

题目描述

魔法王国一共有n个城市,编号为0~n-1号,n个城市之间的道路连接起来恰好构成一棵树。小易现在在0号城市,每次行动小易会从当前所在的城市走到与其相邻的一个城市,小易最多能行动L次。如果小易到达过某个城市就视为小易游历过这个城市了,小易现在要制定好的旅游计划使他能游历最多的城市,请你帮他计算一下他最多能游历过多少个城市(注意0号城市已经游历了,游历过的城市不重复计算)。

输入描述

输入包括两行,第一行包括两个正整数n(2 ≤ n ≤ 50)和L(1 ≤ L ≤ 100),表示城市个数和小易能行动的次数。第二行包括n-1个整数parent[i](0 ≤ parent[i] ≤ i), 对于每个合法的i(0 ≤ i ≤ n - 2),在(i+1)号城市和parent[i]间有一条道路连接。

输出描述

输出一个整数,表示小易最多能游历的城市数量。

示例

输入

5 2
0 1 2 3

输出

3

解题代码

拿到这道题,说实话,我也想了很久,甚至试了深度优先搜索,但是如果仅有简单的数组数据结构,深度优先搜索是做不出maxLength,即一次搜索最长的长度。原因是我漏看了题目一个最重要的信息!不废话,先上代码,然后再一步步介绍如何做的。

#include<iostream>
#include<vector>
using namespace std;

int solveMaxLen(int, vector<int>, vector<int>);
int max(int, int);

int main(){
    //思路:1、首先,先搜索出最长的深度,即每一次走都不走回头路
    int n, L, maxLength;
    cin >> n >> L;
    vector<int> parent;
    vector<int> dp(n, 0);
    int temp;
    for (int i = 0; i < n - 1; i++){
        cin >> temp;
        //比如:parent[0]与1之间有一条边相连
        parent.push_back(temp);
    }
    maxLength = solveMaxLen(n, dp, parent);
    //首先,如果L小于最长的深度,那么就是说还没走到最深处就停止了,那么此时游历的国家就为L+1
    if (maxLength - 1>=L){
        cout << L + 1;
    }
    //如果L大于最长的深度,那么此时肯定会有重复走的路,对于某个点A来说,如果想绕弯来游历它,那么就需要先走到A,然后再走到A的父节点,于是每游历一个要重复的国家,需要2次,所以
    //(n - maxLength + 1)表示除了最长的深度上的节点外的其它节点,
    //(n - maxLength + 1) * 2 + maxLength - 1表示如果要游历完所有国家的总次数,若总次数>L,那么(L - maxLength + 1) / 2表示能游历的重复国家数,maxLength表示在最长的深度上的国家数
    else if (maxLength - 1 < L && (n - maxLength + 1) * 2 + maxLength - 1 >= L){
        cout << (L - maxLength + 1) / 2 + maxLength;
    }
    //如果L比要游历完所有国家所需的总次数还大,那么就直接输出所有的国家
    else{
        cout << n;
    }
    system("pause");
    return 0;
}

int solveMaxLen(int n, vector<int> dp, vector<int> parent){
    dp[0] = 1;
    int maxLen = 0;
    for (int i = 1; i < n; i++){
        dp[i] = dp[parent[i-1]] + 1;
        maxLen = max(maxLen, dp[i]);
    }
    return maxLen;
}

int max(int a, int b){
    if (a > b){
        return a;
    }
    else{
        return b;
    }
}

思路阐述

首先,回到题目中来,其实题目已经透露了很多隐藏信息:
1、“一棵树”,让人想到树的数据结构;
2、“parent”是不是树的父节点呢?那根据题目意思,parent[i]是不是第i+1个节点的父节点呢?答案是肯定的,因为有一个约束 parent[i]必须 ≤ i,即如果游历的话,会先游历parent[i]再游历节点 i+1
这里写图片描述
于是,根据题目的意思,很容易想到dp(动态规划),即访问第i个节点时,可以先访问parent[i-1]节点,再走一步到达节点i,dp[i] = dp[ parent[i-1] ]+1;根据这个公式,很容易就做出了树的深度。

对于,判断条件,我在代码中已经注明了,大家可以参照我的代码。

猜你喜欢

转载自blog.csdn.net/m0_37885286/article/details/79488526