【LeetCode 1723】DP解法 Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务

111 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务活动详情

一、题目描述

给定n个工人,和m个任务,每个任务有完成所需的时间,工人都是一样的。求一个分配方案,最小化最大的工人耗时,输出这个方案。

数据范围

n <= 12

二、思路分析

动态规划+状态压缩

j表示在二进制下选择了哪些任务,我们设f[i][j]表示i个工人,完成了集合j的任务所花费的最小时间。 显然可得方程 f[i][j] = min(f[i][j], max(f[i-1][j^s], sum[s]))

其中sum[s]表示一个工人完成集合s的任务所花费的时间,sj的子集,j^s表示集合j减去集合s。从通俗意义上理解就是尝试把某部分任务单独划出来给一个工人去做。

三、AC代码

class Solution {
public:

    int js(vector<int>  jobs, int x){
        int ans=0;
        for (int i=0; (1<<i)<=x; i++){
            if ((1<<i)&x){
                ans += jobs[i];
            }
        }
        return ans;
    }

    int minimumTimeRequired(vector<int> jobs, int k) {
        int f[13][5000], sum[5000], m = jobs.size();
        for (int i=0; i<=12; i++)
        for (int j=0; j<4999; j++) f[i][j] = 999999999;
        for (int i=0; i<=(1<<m)-1; i++) sum[i] = js(jobs, i);
        for (int j=0; j<(1<<m); j++) {
            f[1][j] = sum[j];
        }


        for (int i=2; i<=k; i++) {
            for (int j=1; j<(1<<m); j++) {
                //f[i][j] = min(f[i-1][j-s]+sum[s])
                for (int s=0; s<(1<<m); s++)
                if ((s|j) == j) {
                    f[i][j] =min(f[i][j], max(f[i-1][j^s], sum[s]));
                }
            }
        }
        return f[k][(1<<m)-1];
    }
};

四、总结

写的时候一直挂细节,对于动态规划类的题目,应该放慢写的速度,仔细想清楚每个转移的边界、条件,才能够最大程度避免出现问题,而且这种调试起来很难受,基本上只能对着代码看是哪里挂了。