如何解决“管理你的能量”?

时间:2013-04-27 04:01:55

标签: algorithm dynamic-programming

我在Google Code Jam中阅读了optimisation problem about energy。 (比赛结束了,所以可以谈论它)

  

今天你的日历非常繁忙,有很多重要的事情要做。   你努力准备并确保所有的活动都没有   交叠。现在是早上,你担心尽管如此   热情,你将无法全力以赴地完成这一切   接合。

     

你必须仔细管理你的能量。你开始一整天   能量 - 准确地说是能量的E焦耳。你知道你不能去   低于零焦耳,或者你将从疲惫中堕落。你可以花任何钱   每项活动的非负,整数焦耳(您可以花费   零,如果你觉得懒惰),并在每次活动后你将重新获得R.   焦耳的能量。然而,无论你多么懒惰,你都不能拥有   任何时候都超过E焦耳的能量;你会有多余的能量   重拾过去这一点是浪费。

     

现在,有些事情(比如解决Code Jam问题)更为重要   相对于其它的。对于第i个活动,您有一个表达的值vi   这项活动对你有多重要。你从每个人获得的收益   活动是活动的价值,乘以金额   你花在活动上的能量(焦耳)。你想管理你的   能量使你的总收益尽可能大。

     

请注意,您无法对日历中的活动重新排序。你刚才   必须用你的日历来管理你的能量   有

     

输入

     

输入的第一行给出了测试用例的数量,T.T test   案件如下。每个测试用例由两行描述。首先   包含三个整数:E,最大(和初始)量   能量,R,每次活动后你恢复的数量,和N,   当天计划的活动数量。第二行包含N.   整数vi,描述您计划的活动的价值   今天。

     

输出

     

对于每个测试用例,输出一行包含“Case #x:y”,其中x   是案例编号(从1开始),y是您可以获得的最大增益   通过当天管理你的能量来实现。

如何解决这个问题?我在想它是否可以通过动态编程来解决。任何线索?

2 个答案:

答案 0 :(得分:1)

它可以简单地通过递归完成,下面附带代码:这里状态是v的数组,如问题

    public static long calculate(long limit,long initialEnergy,long R,long[] status,int start){
    long leftEnergy = 0;
    long  maxGain = 0;
    if(start + 1 > status.length){
        return  0;
    }
    for(long taskEnergy = initialEnergy; taskEnergy>=0;taskEnergy--){
        leftEnergy = initialEnergy - taskEnergy + R;
        if(leftEnergy > limit){
            leftEnergy = limit;
        }
        long gain = status[start] * taskEnergy + calculate(limit,leftEnergy, R, status, start +1);
        if(gain > maxGain){
            maxGain = gain;
        }
    }
    //System.out.println(start + " " +  maxGain);
    return maxGain;
}

答案 1 :(得分:-1)

想象一下在每个活动上花费的能量作为多维空间中的坐标。想象一下,作为多维空间中点的温度而获得的增益。 (将不可能的组合视为零增益。)这将问题减少为“找到房间中最热点”。这很容易 - 从任何地方开始(可能,为简单起见,从每个活动消耗的零能量开始,因为至少确保合法),继续向任何方向移动,使其更热,并在没有方向使其更热时停止。

直观地说,在我看来,你不能陷入局部最大值(因为输出是输入的线性,钳位函数)。但是如果你担心它,当你停下来时,“随意”踢自己“然后再试一次。如果你重复这几次并在同一地点持续着陆,你可以合理地确信这是全球最大值。

使用重力隐喻,基本上,您将问题映射到空间。您将最佳解决方案映射到空间中的最低点。然后它就像落到底部一样简单。