/* Topcoder TCO 2017, Q1A 500-Pointer - CheeseSlicing James S. Plank Fri Apr 7 16:05:47 EDT 2017 */ #include #include #include #include #include #include #include #include #include #include using namespace std; class CheeseSlicing { public: int totalArea(int A, int B, int C, int S); vector < vector < vector > >Cache; }; int CheeseSlicing::totalArea(int A, int B, int C, int S) { int i, j, best; vector Sorted; /* First, initialize the cache if this is the very first call. */ if (Cache.size() == 0) { Cache.resize(A+1); for (i = 0; i < Cache.size(); i++) { Cache[i].resize(B+1); for (j = 0; j < Cache[i].size(); j++) Cache[i][j].resize(C+1, -1); } } /* Sort the slices -- this makes it easier to find the "shortest" slice. */ if (Cache[A][B][C] != -1) return Cache[A][B][C]; Sorted.push_back(A); Sorted.push_back(B); Sorted.push_back(C); sort(Sorted.begin(), Sorted.end()); /* Base case: If the smallest side is less than S, then you have a bad slice -- return 0. */ if (Sorted[0] < S) return 0; /* Otherwise, first calculate the surface area if you make no cuts. */ best = Sorted[1] * Sorted[2]; /* Then, for each side, if slicing along that side yields two "good" pieces, go ahead and make the recursive call for each of these, and sum up the results. Use the maximum of these. */ if (A-S >= S) { i = totalArea(A-S, B, C, S) + totalArea(S, B, C, S); if (i > best) best = i; } if (B-S >= S) { i = totalArea(A, B-S, C, S) + totalArea(A, S, C, S); if (i > best) best = i; } if (C-S >= S) { i = totalArea(A, B, C-S, S) + totalArea(A, B, S, S); if (i > best) best = i; } Cache[A][B][C] = best; return best; }