洗车概率

时间:2019-04-13 06:06:03

标签: python algorithm dynamic-programming

我正在尝试解决以下DP问题:

洗车公司的一名员工的目标是在接下来的D天之内洗净C辆汽车。由于日程安排和用品的限制,他一天最多只能洗D i 辆汽车。对他来说幸运的是,他已提前D天向他提供了每天最多可洗车的清单,例如[第1天= 2辆,第2天= 3辆,第3天= 4辆)。他可以在D天的时间内达到多少种清洗C辆汽车的目标,从而使这些天的总汽车总数等于C。他每天必须至少洗1辆汽车。他无法在D天后的几天内达到目标,因此必须在D天之内准确完成。

3 个答案:

答案 0 :(得分:1)

这是一种动态编程解决方案,可以在O(D*C*C)时间内工作;

D = 3,C到10的样本矩阵,其极限为[2,3,4]。

sample

int NumberOfWays(int c, int d, int[] limits)
{
    // let's t[i, j] be amount of ways j cars can be washed in i days

    var t = new int[d + 1, c + 1];

    for (int day = 1; day <= d; day++)
    {
        int dayLimit = limits[day - 1];

        for (int cars = day; cars <= c; cars++)
        {
            if (day == 1) // first day
            {
                if (cars <= dayLimit)
                    t[day, cars] = 1;
            } else // not first day
            {
                // okay, number of ways given amount of cars can be washed
                // on certain day can be calculated using amounts possible on the previous day

                for (int carsOnPrevDay = 1; carsOnPrevDay < cars; carsOnPrevDay++)
                {
                    if (cars - carsOnPrevDay > dayLimit)
                        continue; // day limit exceeded

                    t[day, cars] += t[day - 1, carsOnPrevDay];
                }
            }
        }
    }

    return t[d, c];
}

答案 1 :(得分:1)

注意:问题与另一个常见问题相同:使用带有d1,d2,d3,...,dn边的骰子滚动给定总数的有几种方法。

如果在i天内有C [n,i]种方式清洗n辆汽车,那么有sum(C [nk],i + 1),k = 1..D [i + 1])方式清洗n辆汽车在i + 1天之内。在边缘条件下:C [0,0] = 1,C [0,_] = 0。

这直接给出了O(Cmax(D)| D |)算法,该算法使用O(C)空间。

def cars(C, D):
    r = [1] + [0] * C
    for d in D:
        for i in range(C, -1, -1):
            r[i] = sum(r[j] for j in range(max(0, i-d), i))
    return r[C]

print(cars(5, [2, 3, 4]))

您可以做得更好,因为内部循环正在执行d值的滚动总和,这可以平均用C的每个元素的O(1)时间来计算。

def cars(C, D):
    r = [1] + [0] * C
    for d in D:
        S = 0
        for i in range(C, -d-1, -1):
            if i >= 0:
                S += r[i]
            if i + d <= C:
                S -= r[i+d]
                r[i+d] = S
    return r[C]

print(cars(5, [2, 3, 4]))

由于不失一般性,max(D)

如果有帮助,此代码实质上是在计算多项式P [D [0]] * P [D [1]] * ... * P [D [len(D)- 1]],其中P [d] = x + x ^ 2 + ... + x ^ d。结果中的x ^ C系数可以解决您的问题。

答案 2 :(得分:0)

在一个更具教育意义的注解中,我尝试手动运行您的算法(忽略边界问题)并得到以下矩阵:

Yours

但是您可能正在寻找更多的东西(请注意,由于懒惰,我忽略了填写无效值):

Mine

请稍微调整一下总和,尤其是在第一天,由于某些原因,第二天无法洗2或3辆汽车。之后,返回OPT[D, C]是正确的。