(網易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;根據這個公式,很容易就做出了樹的深度。

對於,判斷條件,我在代碼中已經註明了,大家可以參照我的代碼。

發佈了50 篇原創文章 · 獲贊 45 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章