【问题标题】:Assign the work for 2 people so that the time is minimum将工作分配给 2 人,使时间最短
【发布时间】:2022-01-21 19:07:21
【问题描述】:

问题:

N 件作品需要分配给 2 人。人 A 可以在 a[i] 时间内完成工作 i,人 B可以在 b[i] 时间内完成工作。

每项工作只能分配给 1 人。分配好作品后,每个人各自做自己的作品。

总时间将是 2 人所用总时间中较大的一个。

找到一种分配工作的方法,使总时间最短。

示例:

N = 6
a[] = 10 100 30 50 50 80
b[] = 100 30 40 40 60 90

Answer: 130

Explaination:

Person A do work 1, 3, 6 -> total time: 120
Person B do work 2, 4, 5 -> total time: 130

Overall time: 130

限制:

N <= 100
a[i], b[i] <= 30.000

我的看法

我尝试用动态编程解决它,更具体地说:DP[i][p][c] i 是到目前为止完成的工作数量,p 是到目前为止 A 人的总时间,c 是 B 人的总时间,所以远的。对于每个 i,我们可以尝试将工作分配给 A 或 B,然后将最佳答案保存在 DP[i][p][c] 中,这样我们就不必重新计算了。

pc 可以达到 3.000.000,所以我尝试将其缩小到 DP[i][max(p,c)]

下面的代码给出了示例案例的正确答案,以及我生成的其他案例:

int n, firstCost[105], secondCost[105];
int dp[105][300005];

int solve(int i, int p, int c){
    if(i > n) return max(p, c);

    int &res = dp[i][max(p, c)];
    if(res != -1) return res;

    res = INT_MAX;
    int tmp1 = solve(i+1, p + firstCost[i], c);
    int tmp2 = solve(i+1, p, c + secondCost[i]);

    res = min(tmp1, tmp2);
    return res;
}

int main(){
    // input...
    cout << solve(1, 0, 0);
}

但是当我提交它时,它给出了错误的答案:

20
4034 18449 10427 4752 8197 7698 17402 16164 12306 5249 19076 18560 16584 18969 3548 11260 6752 18052 14684 18113
19685 10028 938 10379 11583 10383 7175 4557 850 5704 14156 18587 2869 16300 15393 14874 18859 9232 6057 3562

我的输出是77759,但答案应该是80477

我不知道我做错了什么,有什么办法可以改进我的解决方案吗?

P/S:

Here's the original problem,页面是越南语,你可以创建一个帐户并在那里提交

【问题讨论】:

  • @Yunnosch 我已经添加了对我的解决方案的更好解释,请检查
  • @Yunnosch n 最多 20,这种情况的可能性太多,我无法弄清楚我错的确切点
  • 我把它做得最小但可以理解

标签: c++ algorithm dynamic-programming


【解决方案1】:

您缺少的技巧是最佳边缘的想法。

您正试图将其缩小到 max(p,c),但很可能您需要将前半部分工作发送给人 A,而这最初看起来像是一组糟糕的选择.你是对的,你可以通过 DP[i][p][c] 得到正确的答案,但很快就会产生太多数据。

但假设p0 &lt;= p1c0 &lt;= c1。那么,查看通过(p1, c1) 的路径绝对不可能得到比(p0, c0) 更好的答案。因此我们可以立即删除(p1, c1)

我不会给你代码,但我会从你的例子中向你展示一些如何开始的。

4034 18449 10427 4752 8197 7698 17402 16164 12306 5249 19076 18560 16584 18969 3548 11260 6752 18052 14684 18113
19685 10028 938 10379 11583 10383 7175 4557 850 5704 14156 18587 2869 16300 15393 14874 18859 9232 6057 3562

首先我们从DP = [[0,0]]开始。

在我们分配第一个元素后,您会得到[[0,19685], [4034,0]]

在我们分配第二个得到之后,[[0,29713], [4034,10028], [18449,19685], [22483,0]]。我们可以放弃[18449,19685],因为它不如[4034,10028],所以我们得到[[0,29713], [4034,10028], [22483,0]]

第三个元素给出[[0,30651], [4034,10966], [10427,29713], [14461,10028], [22483,938], [32910,0]],然后我们可以删除[10427,29713],因为它比[4034,10966] 更差。现在我们在[[0,30651], [4034,10966], [14461,10028], [22483,938], [32910,0]]

等等。

作为额外的优化,我首先将索引按c[i]/p[i] 排序并产生一个贪婪的解决方案,我们将所有开始索引分配给 A 并将所有结束索引分配给 B 。从那个贪婪的解决方案的存在来看,我们永远不需要查看任何比已知解决方案更糟糕的pc 解决方案。在我们完成工作的一半之后,这应该成为一个有用的过滤器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多