LeetCode wants to give one of its best employees the option to travel among N cities to collect algorithm problems. But all work and no play makes Jack a dull boy, you could take vacations in some particular cities and weeks. Your job is to schedule the traveling to maximize the number of vacation days you could take, but there are certain rules and restrictions you need to follow.

Rules and restrictions:

  1. You can only travel among N cities, represented by indexes from 0 to N-1. Initially, you are in the city indexed 0 on Monday.
  2. The cities are connected by flights. The flights are represented as a N*N matrix (not necessary symmetrical), called flights representing the airline status from the city i to the city j. If there is no flight from the city i to the city j, flights[i][j] = 0; Otherwise, flights[i][j] = 1. Also, flights[i][i] = 0 for all i.
  3. You totally have K weeks (each week has 7 days) to travel. You can only take flights at most once per day and can only take flights on each week's Monday morning. Since flight time is so short, we don't consider the impact of flight time.
  4. For each city, you can only have restricted vacation days in different weeks, given an N*K matrix called days representing this relationship. For the value of days[i][j], it represents the maximum days you could take vacation in the city i in the week j.

You're given the flights matrix and days matrix, and you need to output the maximum vacation days you could take during K weeks.

Example 1:

  1. Input:flights = [[0,1,1],[1,0,1],[1,1,0]], days = [[1,3,1],[6,0,3],[3,3,3]]
  2. Output: 12
  3. Explanation:
    Ans = 6 + 3 + 3 = 12.
  4. One of the best strategies is:
  5. 1st week : fly from city 0 to city 1 on Monday, and play 6 days and work 1 day.
    (Although you start at city 0, we could also fly to and start at other cities since it is Monday.)
  6. 2nd week : fly from city 1 to city 2 on Monday, and play 3 days and work 4 days.
  7. 3rd week : stay at city 2, and play 3 days and work 4 days.

Example 2:

  1. Input:flights = [[0,0,0],[0,0,0],[0,0,0]], days = [[1,1,1],[7,7,7],[7,7,7]]
  2. Output: 3
  3. Explanation:
    Ans = 1 + 1 + 1 = 3.
  4. Since there is no flights enable you to move to another city, you have to stay at city 0 for the whole 3 weeks.
    For each week, you only have one day to play and six days to work.
    So the maximum number of vacation days is 3.

Example 3:

  1. Input:flights = [[0,1,1],[1,0,1],[1,1,0]], days = [[7,0,0],[0,7,0],[0,0,7]]
  2. Output: 21
  3. Explanation:
    Ans = 7 + 7 + 7 = 21
  4. One of the best strategies is:
  5. 1st week : stay at city 0, and play 7 days.
  6. 2nd week : fly from city 0 to city 1 on Monday, and play 7 days.
  7. 3rd week : fly from city 1 to city 2 on Monday, and play 7 days.

Note:

  1. N and K are positive integers, which are in the range of [1, 100].
  2. In the matrix flights, all the values are integers in the range of [0, 1].
  3. In the matrix days, all the values are integers in the range [0, 7].
  4. You could stay at a city beyond the number of vacation days, but you should work on the extra days, which won't be counted as vacation days.
  5. If you fly from the city A to the city B and take the vacation on that day, the deduction towards vacation days will count towards the vacation days of city B in that week.
  6. We don't consider the impact of flight hours towards the calculation of vacation days.

这道题给了我们一个NxN的数组,表示城市i是否有飞机直达城市j,又给了我们一个NxK的数组days,表示在第j周能在城市i休假的天数,让我们找出一个行程能使我们休假的天数最大化。开始尝试写了个递归的暴力破解法,结果TLE了。其实这道题比较适合用DP来解,我们建立一个二维DP数组,其中dp[i][j]表示目前是第j周,并且在此时在城市i,总共已经获得休假的总日子数。我们采取从后往前更新的方式(不要问我为什么,因为从前往后更新的写法要复杂一些),我们从第k周开始往第一周遍历,那么最后结果都累加在了dp[i][0]中,i的范围是[0, n-1],找出其中的最大值就是我们能休息的最大假期数了。难点就在于找递推式了,我们想dp[i][j]表示的是当前是第j周并在城市i已经获得的休假总日子数,那么上一个状态,也就是j+1周(因为我们是从后往前更新),跟当前状态有何联系,上一周我们可能还在城市i,也可能在其他城市p,那么在其他城市p的条件是,城市p有直飞城市i的飞机,那么我们可以用上一个状态的值dp[p][j+1]来更新当前值dp[i][j],还要注意的是我们要从倒数第二周开始更新,因为倒数第一周没有上一个状态,还有就是每个状态dp[i][j]都初始化赋为days[i][j]来更新,这样一旦没有任何城市可以直飞当前城市,起码我们还可以享受当前城市的假期,最后要做的就是想上面所说在dp[i][0]中找最大值,下面的代码是把这一步融合到了for循环中,所以加上了一堆判断条件,我们也可以在dp数组整个更新结束之后再来找最大值,参见代码如下:

解法一:

  1. class Solution {
  2. public:
  3. int maxVacationDays(vector<vector<int>>& flights, vector<vector<int>>& days) {
  4. int n = flights.size(), k = days[].size(), res = ;
  5. vector<vector<int>> dp(n, vector<int>(k, ));
  6. for (int j = k - ; j >= ; --j) {
  7. for (int i = ; i < n; ++i) {
  8. dp[i][j] = days[i][j];
  9. for (int p = ; p < n; ++p) {
  10. if ((i == p || flights[i][p]) && j < k - ) {
  11. dp[i][j] = max(dp[i][j], dp[p][j + ] + days[i][j]);
  12. }
  13. if (j == && (i == || flights[][i])) res = max(res, dp[i][]);
  14. }
  15. }
  16. }
  17. return res;
  18. }
  19. };

下面这种方法优化了空间复杂度,只用了一个一维的DP数组,其中dp[i]表示在当前周,在城市i时已经获得的最大假期数,并且除了第一个数初始化为0,其余均初始化为整型最小值,然后我们从第一周往后遍历,我们新建一个临时数组t,初始化为整型最小值,然后遍历每一个城市,对于每一个城市,我们遍历其他所有城市,看是否有飞机能直达当前城市,或者就是当前的城市,我们用dp[p] + days[i][j]来更更新dp[i],当每个城市都遍历完了之后,我们将t整个赋值给dp,然后进行下一周的更新,最后只要在dp数组中找出最大值返回即可,这种写法不但省空间,而且也相对简洁一些,很赞啊~

解法二:

  1. class Solution {
  2. public:
  3. int maxVacationDays(vector<vector<int>>& flights, vector<vector<int>>& days) {
  4. int n = flights.size(), k = days[].size();
  5. vector<int> dp(n, INT_MIN);
  6. dp[] = ;
  7. for (int j = ; j < k; ++j) {
  8. vector<int> t(n, INT_MIN);
  9. for (int i = ; i < n; ++i) {
  10. for (int p = ; p < n; ++p) {
  11. if (i == p || flights[p][i]) {
  12. t[i] = max(t[i], dp[p] + days[i][j]);
  13. }
  14. }
  15. }
  16. dp = t;
  17. }
  18. return *max_element(dp.begin(), dp.end());
  19. }
  20. };

之前提到了递归的DFS会TLE,但是如果我们使用一个memo数组来保存中间计算结果,就能省去大量的重复计算,并且能够通过OJ,解题思想跟解法一非常的类似,参见代码如下:

解法三:

  1. class Solution {
  2. public:
  3. int maxVacationDays(vector<vector<int>>& flights, vector<vector<int>>& days) {
  4. int n = flights.size(), k = days[].size();
  5. vector<vector<int>> memo(n, vector<int>(k, ));
  6. return helper(flights, days, , , memo);
  7. }
  8. int helper(vector<vector<int>>& flights, vector<vector<int>>& days, int city, int day, vector<vector<int>>& memo) {
  9. int n = flights.size(), k = days[].size(), res = ;
  10. if (day == k) return ;
  11. if (memo[city][day] > ) return memo[city][day];
  12. for (int i = ; i < n; ++i) {
  13. if (i == city || flights[city][i] == ) {
  14. res = max(res, days[i][day] + helper(flights, days, i, day + , memo));
  15. }
  16. }
  17. return memo[city][day] = res;
  18. }
  19. };

参考资料:

https://discuss.leetcode.com/topic/87865/java-dfs-tle-and-dp-solutions/2

https://discuss.leetcode.com/topic/87869/c-clean-code-graphic-explanation

https://discuss.leetcode.com/topic/89353/short-java-recursion-dfs-memoization

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Maximum Vacation Days 最大化休假日的更多相关文章

  1. [LeetCode] 568. Maximum Vacation Days 最大化休假日

    LeetCode wants to give one of its best employees the option to travel among N cities to collect algo ...

  2. LeetCode 568. Maximum Vacation Days

    原题链接在这里:https://leetcode.com/problems/maximum-vacation-days/ 题目: LeetCode wants to give one of its b ...

  3. 568. Maximum Vacation Days

    Problem statement:  LeetCode wants to give one of its best employees the option to travel among N ci ...

  4. LeetCode:Maximum Depth of Binary Tree_104

    LeetCode:Maximum Depth of Binary Tree [问题再现] Given a binary tree, find its maximum depth. The maximu ...

  5. LeetCode Maximum Product Subarray(枚举)

    LeetCode Maximum Product Subarray Description Given a sequence of integers S = {S1, S2, . . . , Sn}, ...

  6. LeetCode——Maximum Depth of Binary Tree

    LeetCode--Maximum Depth of Binary Tree Question Given a binary tree, find its maximum depth. The max ...

  7. [LeetCode] Maximum XOR of Two Numbers in an Array 数组中异或值最大的两个数字

    Given a non-empty array of numbers, a0, a1, a2, … , an-1, where 0 ≤ ai < 231. Find the maximum re ...

  8. [LeetCode] Maximum Size Subarray Sum Equals k 最大子数组之和为k

    Given an array nums and a target value k, find the maximum length of a subarray that sums to k. If t ...

  9. [LeetCode] Maximum Product of Word Lengths 单词长度的最大积

    Given a string array words, find the maximum value of length(word[i]) * length(word[j]) where the tw ...

随机推荐

  1. 将 Shiro 作为应用的权限基础 四:shiro的配置说明

    Apache Shiro的配置主要分为四部分: SecurityManager的配置 URL过滤器的配置 静态用户配置 静态角色配置 其中,由于用户.角色一般由后台进行操作的动态数据,比如通过@Req ...

  2. Jquery点击除了指定div元素其他地方,隐藏该div

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script ty ...

  3. JavaWeb学习笔记总结 目录篇

    JavaWeb学习笔记一: XML解析 JavaWeb学习笔记二 Http协议和Tomcat服务器 JavaWeb学习笔记三 Servlet JavaWeb学习笔记四 request&resp ...

  4. 关于伪类after后续追加,实现js事件(如点击事件)

    实现情况为:点击"编辑"后,"编辑"文字变成"完成",再点击伪类元素后的"完成",此时的"完成"应该 ...

  5. 网络1711-1712的C语言作业总结(2017-2018第一学期)

    1.第0次作业总结--预备作业 作业地址 1711班级总结 1712班级总结 2.第一次作业总结--顺序结构 作业地址 1711班级总结 1712班级总结 3.第二次作业总结--分支结构 作业地址 1 ...

  6. 【Alpha版本】冲刺阶段 - Day1 - 启航

    Alpha 阶段成员分工及任务量 成员 分工 任务量(小时) 袁逸灏 完成app用户车辆,子弹发射,背景移动,暂停界面,音乐界面,音乐查找,音乐播放 25 刘伟康 项目进度把控.分配任务.组织会议.整 ...

  7. Beta冲刺置顶随笔

    项目名称:城市安全风险管控系统 小组成员: 张梨贤.林静.周静平.黄腾飞 Beta冲刺随笔 Beta预备 Beta冲刺Day1 Beta冲刺Day2 Beta冲刺Day3 Beta冲刺Day4 Bet ...

  8. HTTP协议中PUT和POST使用区别

          有的观点认为,应该用POST来创建一个资源,用PUT来更新一个资源:有的观点认为,应该用PUT来创建一个资源,用POST来更新一个资源:还有的观点认为可以用PUT和POST中任何一个来做创 ...

  9. SpaceVim - 让你的vim变得更加高效和强大

    SpaceVim 中文手册 项 目 主 页: https://spacevim.org Github 地址 : https://github.com/SpaceVim/SpaceVim SpaceVi ...

  10. 微信小程序轮播图

    swiper标签 <!--index.wxml--> <swiper class="swiper" indicator-dots="true" ...