题目:
在这里插入图片描述
在这里插入图片描述


题解:

思路:状压 dp,枚举子集,学习枚举状态 i 子集的方法。由于 n<=20,可以很方便的使用一个 n 位二进制来表示每个数选与不选。

  • 1)预处理 dp 数组,将[0,2^n-1]的所有二进制状态 s 中构成的子集的时间 <= sessionTime 的 dp[s] 初始化为 1。
  • 2)进行状态转移方程,即每个状态 s 枚举其子集,更新最小的 dp[s],子集 j 可以从 s 开始枚举,也可以从 s&(s-1) 开始枚举,j 在 s 内的补集为 j ^ s ,然后我们更新 dp[s] 的话,就是取min(dp[s],dp[j]+dp[h ^ s])。

代码如下:

class Solution {
public:
    int minSessions(vector<int>& tasks, int sessionTime) {
        int n=tasks.size();
        vector<int> f(1<<n,20);
        // 枚举子集,[0,2^n-1]之间的所有二进制数,哪些位为1则在tasts中选取那些数字
        for(int s=1;s<1<<n;++s){
            int spend=0;
            for(int i=0;i<n;++i){
                // s的第i位为1,则选取这个数字
                if(s>>i&1)spend+=tasks[i];
            }
            // 该小子集满足情况
            if(spend<=sessionTime)f[s]=1;
        }
        // 开始对每个状态枚举子集
        for(int s=1;s<1<<n;++s){
            if(f[s]==1)continue;
            for(int j=(s-1)&s;j>s>>1;j=(j-1)&s){
                // j为s的子集,s^j=s1为j在s内的补集,即s1∪j=s
                f[s]=min(f[s],f[j]+f[s^j]);
            }
        }
        return f[(1<<n)-1];
    }
};
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐