引发生活编码问题-如何解决此类问题

时间:2019-01-20 01:21:32

标签: algorithm time-complexity dynamic-programming greedy

请帮助我给我一些解决方法。我的想法是贪婪的方法。

问题是:

您在俄罗斯萨马拉(Samara)工作几天,每天都有每单位工作的新工资和每单位食物的新费用。工作1单位需要1单位能量,而吃1单位食物则要增加1单位能量。这里 以下是您的工作要求:

+您到达时一无所有,但精力充沛。您永远不会拥有比到达的能量更多的能量,而且它永远不会是负面的。

+您每天可以做任何数量的工作(可能根本不做任何工作),仅受您的精力限制。当能量为零时,您将无法工作。

+您每天可以吃任何数量的食物(可能根本没有任何食物),受您拥有的钱的限制。当您的钱为零时,您将无法吃饭。

+您可以在一天结束时吃东西,并且吃完饭后不能恢复工作。您可以在第二天恢复工作。 您的真实目标是带回尽可能多的钱。计算您可以带回家的最大金额。

例如,考虑一个3天的住宿,其中每天每单位工作的工资如下:收入= [1、2、4]。食物的成本是成本= [1、3、6]。您从e = 5能量单位开始。

*第一天:1个单位的工作价值1,1个单位的食品成本1.今天没有上班的经济诱因。

*第二天:每工作1单位可赚2,而每工作1单位的食品成本3,因此您吃的东西比总收入要多,因此这一天没有上班的经济诱因。

*第三天:您每工作一个单元可获得4个单元。今天的食物成本是无关紧要的,因为您要直接下班回家。您将所有精力都花在工作上,收取报酬:5 x 4 = 20单位 钱,不用买晚餐就回家。

功能说明 在下面的编辑器中完成函数calculateProfit。该函数必须返回一个整数,该整数表示在住宿结束后可以带回家的最大收入。

到目前为止,我的解决方案(需要改进):

function calculateProfit(n, earning, cost, e) {
    // Write your code here

    let sum = 0

    let ef = e;

    let count = 0;

    let max = 0;

    for (let i = 0; i < n; i++){

        if (i != n - 1) {


                console.log("next day " + ef + " " + ef * earning[i + 1] + "--" + ef * cost[i]);

                if (earning[i] > cost[i]) {

                    sum += ef * earning[i];
                    e = 0;

                    max = 0;

                    if (ef * earning[i + 1] > ef * cost[i] && sum > 0) {

                        //console.log(e);
                        sum -= ef * cost[i];
                        e = ef;
                    }


                }
                else {
                    count++;
                    max = Math.max(max, earning[i]);
                }             




        }
        else {//last day

            if (earning[i] <= cost[i]) {
                count++;                
            }

            max = Math.max(max, earning[i]);

            if (e > 0)
                sum += ef * max;

        }

        console.log(i, "-", sum," max=",max);

    }

    console.log("count",count);    

    if (count == n) {
        earning.sort();
        sum = earning[n-1] * ef;
    }

    return sum;

}

1 个答案:

答案 0 :(得分:0)

不幸的是,不同的日子不能分开考虑。考虑一个例子,其中劳动和食品在第一天都很昂贵,而第二天又便宜。显然,您将在第一天工作,然后在第二天进餐。

那么,我们该如何解决呢?具有动态程序。在每一天中,您必须做出两个选择:您工作多少,吃多少?一天结束时,您将获得一些总收入和一定的精力。该能量值只能在0和最大能量之间具有几个不同的值。

让我们将两个决策分开,并跟踪每个剩余能量水平的最大收益。假设E_afterWork(day: i, energy: e)是您在工作第i天和剩余能量e后可获得的最高收入。同样,E_afterEat(day: i, energy: e)是在i一天进餐后的最大收入。我们将持续跟踪这些值。最后,我们对E_afterWork(day: totalDays - 1, energy: 0)感兴趣。这就是我们剩下的钱。

第一天,我们可以立即将E_afterWork设置为:

E_afterWork(day: 0, energy: e) = earning[0] * (maxEnergy - e)

我们在所有能级上都这样做。

然后,我们必须逐渐更新E_afterEatE_afterWork。这些是:

E_afterEat(day: i, energy: e) = maximum over possible previous energy pe (E_afterWork(day: i, energy: pe) - cost[i] * (e - pe))

我们必须检查所有小于或等于pe的{​​{1}}值,以及在哪里可以买得起的食物,即结果是否定的。后者应该自动完成,而无需做任何特别的事情。

我们在这里做什么?我们检查当天(下班后)所有可能的结局,并尝试吃不同量的食物。我们保留了使我们获得最大收益的选择(通过将收益计算为完成工作后的收益减去食品成本)。

现在,如何更新e?这实际上很简单:

E_afterWork

这里的想法相同。

让我们举个例子:

E_afterWork(day: i, energy: e) = maximum over possible previous energy pe (E_afterEat(day: i-1, energy: pe) + earning[i] * (pe - e))

让我们初始化。我将用earning=[7, 2, 4] cost=[7, 3, 6] maxEnergy=5 缩写E_afterWork,用AW缩写E_afterEat

AE

现在更新e | AW(0, e) --+---------- 5 | 0 4 | 7 3 | 14 2 | 21 1 | 28 0 | 35 。对于第一个条目,我们将计算:

AE

下一个工作日:

AE(0, 5) = min (0 - 0 * 7, 7 - 1 * 7, 14 - 2 * 7, 21 - 3 * 7, …) = 0

e | AW(0, e)  AE(0, e)
--+--------------------
5 |    0         0   
4 |    7         7
3 |   14        14
2 |   21        21
1 |   28        28
0 |   35        35

吃:

e | AW(0, e)  AE(0, e)  AW(1, e)
--+-----------------------------
5 |    0         0         0
4 |    7         7         7 = max(0 + 1 * 2, 7 + 0 * 2)
3 |   14        14        14 = max(0 + 2 * 2, 7 + 1 * 2, 14 + 0 * 2)
2 |   21        21        21
1 |   28        28        28
0 |   35        35        35

工作:

e | AW(0, e)  AE(0, e)  AW(1, e)  AE(1, e)
--+---------------------------------------
5 |    0         0         0        20
4 |    7         7         7        23
3 |   14        14        14        26
2 |   21        21        21        29 = max(21 - 0 * 3, 28 - 1 * 3, 35 - 2 * 3)
1 |   28        28        28        32 = max(28 - 0 * 3, 35 - 1 * 3)
0 |   35        35        35        35

因此,在第一天工作,第二天进餐以及最后一天工作,您总共可以获得 40