/*In the last approach, we chose every possible pivot from the range (i, j)(i,j).
But, as per the argument given in Approach 2, we can choose pivots only from the range
\big(i+(len-1)/2,j\big)(i+(len−1)/2,j), where lenlen is the current segment length of interest.
*/
public class Solution {
public int getMoneyAmount(int n) {
int[][] dp = new int[n + 1][n + 1];
for (int len = 2; len <= n; len++) {
for (int start = 1; start <= n - len + 1; start++) {
int minres = Integer.MAX_VALUE;
for (int piv = start + (len - 1) / 2; piv < start + len - 1; piv++) {
int res = piv + Math.max(dp[start][piv - 1], dp[piv + 1][start + len - 1]);
minres = Math.min(res, minres);
}
dp[start][start + len - 1] = minres;
}
}
return dp[1][n];
}
}
public class Solution {
public int getMoneyAmount(int n) {
int[][] dp = new int[n + 1][n + 1];
for (int len = 2; len <= n; len++) {
for (int start = 1; start <= n - len + 1; start++) {
int minres = Integer.MAX_VALUE;
for (int piv = start; piv < start + len - 1; piv++) {
int res = piv + Math.max(dp[start][piv - 1], dp[piv + 1][start + len - 1]);
minres = Math.min(res, minres);
}
dp[start][start + len - 1] = minres;
}
}
return dp[1][n];
}
}
public class Solution {
// TODO
int[][] dp;
public int getMoneyAmount(int n) {
dp = new int[n + 1][n + 1];
return rec(1, n);
}
private int rec(int lo, int hi) {
if (lo >= hi)
return 0;
if (hi == lo + 1)
return lo;
if (dp[lo][hi] > 0)
return dp[lo][hi];
int minCost = Integer.MAX_VALUE, mid = (lo + hi) >> 1;
for (int i = hi - 1; i >= mid; i -= 2) { // i -= 2 ??
minCost = Math.min(minCost, i + Math.max(rec(lo, i - 1), rec(i + 1, hi)));
}
return dp[lo][hi] = minCost;
}
}