leetcode
leetcode 1751 ~ 1800
完成任务的最少工作时间段

完成任务的最少工作时间段

难度:

标签:

题目描述

代码结果

运行时间: 36 ms, 内存: 16.0 MB


/*
 * 思路:
 * 1. 使用位掩码表示任务的组合,dp[i]表示完成任务集合i所需的最小工作时间段数。
 * 2. 使用动态规划方法计算每种任务组合所需的最小工作时间段数。
 * 3. 对于每个任务组合i,尝试将一个新任务加入,更新最小工作时间段数。
 * 4. 使用Java Stream处理任务组合。
 */
import java.util.*;
import java.util.stream.*;

public class MinSessionsStream {
    public int minSessions(int[] tasks, int sessionTime) {
        int n = tasks.length;
        int[] dp = new int[1 << n];
        Arrays.fill(dp, n + 1);
        dp[0] = 1;
        int[] sum = new int[1 << n];

        IntStream.range(0, 1 << n).forEach(i -> {
            IntStream.range(0, n).filter(j -> (i & (1 << j)) == 0).forEach(j -> {
                int next = i | (1 << j);
                if (sum[i] + tasks[j] <= sessionTime) {
                    sum[next] = sum[i] + tasks[j];
                    dp[next] = Math.min(dp[next], dp[i]);
                } else {
                    sum[next] = tasks[j];
                    dp[next] = Math.min(dp[next], dp[i] + 1);
                }
            });
        });

        return dp[(1 << n) - 1];
    }
}

解释

方法:

题解采用深度优先搜索(DFS)加剪枝的策略来找到最小的工作时间段数。首先,将任务按照所需时间的降序排序,以尝试优先处理耗时较长的任务。算法使用了一个数组 used 来跟踪每个时间段已用的总时间。通过递归地尝试将每个任务放入现有的或新的时间段,并检查这是否能够减少总的时间段数。剪枝发生在当前时间段数已经大于或等于已知的最小时间段数时,此时终止当前路径的搜索。该解决方案的关键是尝试所有可能的组合,并通过剪枝来优化搜索。

时间复杂度:

O((cur + 1)^n)

空间复杂度:

O(n)

代码细节讲解

🦆
为什么在DFS中,先尝试将任务放入已有的session而不是直接开启新的session?
在深度优先搜索(DFS)中,先尝试将任务放入已有的session是为了尽可能利用现有的时间段资源,从而减少创建新的session的需求。这种方法有助于尽早填满现有的session,避免过早地增加session数量,从而可能找到需要的最小session数量。此外,这种策略也是为了减少搜索空间,因为开启新的session意味着更多的分支,可能导致复杂度增加。
🦆
为什么题解选择了DFS加剪枝而不是动态规划或贪心算法?
题解选择DFS加剪枝的方法,因为该问题是一个NP难题,涉及到如何将不同任务组合分配到尽可能少的session中,每个session的时间不超过给定限制。动态规划适用于问题具有明确的递推关系和较少的状态数时更为有效,但在本问题中,状态空间可能非常大,因为每个任务加入session的顺序和方式可以非常灵活。而贪心算法虽然实现简单,但不能保证找到全局最优解,只能保证每一步是局部最优。相比之下,DFS可以探索所有可能的任务分配方式,并通过剪枝有效地减少搜索空间,更有可能找到最优解。
🦆
在实现剪枝操作时,具体是如何判断当前路径不再值得探索的?
在实现剪枝操作时,具体的判断方法包括:1. 当前使用的session数量已经达到或超过已知的最小session数量时,继续探索当前路径不太可能产生更优解,因此可以停止当前路径的搜索。2. 当前任务配置已经尝试过,可以通过位运算标记已尝试的配置,避免重复探索相同的配置,从而减少无效的搜索。这两种方法都是为了减少搜索过程中的冗余操作,加速寻找最优解的过程。

相关问题