You have mined a large slab of marble from your quarry. For simplicity, suppose the marble slab is a rectangle measuring n inches in height and m inches in width. You want to cut the slab into smaller rectangles of various sizes – some for kitchen countertops, some for large sculpture projects, others for memorial headstones. You have a marble saw that can make either horizontal or vertical cuts across any rectangular slab. At any given time, you can query the spot price px,y of an x y marble rectangle, for any positive integers x and y. These prices will vary with demand, so do not make any assumptions about them. Given the spot prices, describe an algorithm to compute how to subdivide an n m marble slab to maximize your profit.


Let $M[n,m]$ represent the maximum profit that can be obtained by subdividing an $n \times m$ marble slab. Then using the provided spot price function $p(x,y)$, we observe that if $n=0$ or $m=0$, then $M[n,m] = 0$; otherwise, we have that $M[n,m]$ is: $$ \max\left\{p(n,m),~~\max\limits_{1\leq i\leq \left\lfloor\frac{n}{2}\right\rfloor}\{M[i,m] + M[n-i,m]\},~~\max\limits_{1\leq j\leq \left\lfloor\frac{m}{2}\right\rfloor}\{M[n,j] + M[n,m-j]\}\right\} $$ Intuitively, this is saying that we can either sell the entire slab, make some horizontal cut, or make some vertical cut. We describe this recursion by using the following dynamic programming algorithm:

    if (M[n][m] != NIL) then:
        return // Don't redo work.
    else if (n == 0  or  m == 0) then:
        M[i][j] <- 0 // Base Case.
        max <- 0
        for i <- 1 to floor(n/2) do: // Check all horizontal cuts.
            if (M[i][m] + M[n-i][m] > max) then:
                max <- M[i][m] + M[n-i][m]
        for j <- 1 to floor(m/2) do: // Check all vertical cuts.
            if (M[n][j] + M[n][m-j] > max) then:
                max <- M[n][j] + M[n][m-j]
        if (p(n,m) > max) then: // Should we just sell the entire slab?
            max <- P(n,m)
        M[n][m] <- max

Finally, we initiate everything using the following:

    // Initialize M to be completely NIL.
    for i <- 0 to n do:
        for j <- 0 to m do:
            M[i][j] <- NIL
    // Return the maximum profit and the list of slabs.
    return M[n][m]
  • $\begingroup$ why the n/2 and m/2 devision? $\endgroup$ – nikolaos_mparoutis Jan 5 '14 at 17:17
  • $\begingroup$ By symmetry. For example, suppose that $n = 8$. Then for the horizontal cuts, it suffices to check just: \begin{align*} &M[1,m]+M[7,m] \\&M[2,m]+M[6,m] \\&M[3,m]+M[5,m]\\&M[4,m]+M[4,m]\end{align*} By the commutativity of addition, there is no need to check $M[5,m]+M[3,m]$ and so on. $\endgroup$ – Adriano Jan 5 '14 at 20:13
  • $\begingroup$ ok.But why do you choose i and j , n/2 and m/2 and not at /3 segments. $\endgroup$ – nikolaos_mparoutis Jan 6 '14 at 5:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.