
链接:石头游戏 II
题解:
cpp
class Solution {
public:
/**
* @param arr: An integer array
* @return: An integer
*/
int stoneGame(vector<int> &arr) {
int len = arr.size();
if (len <= 1) {
return 0;
}
int m = 2 * len;
vector<int> a(m);
for (int i = 0; i < m; ++i) {
a[i] = arr[i % len];
}
vector<int> prefix(m + 1, 0);
for (int i = 0; i < m; ++i) {
prefix[i + 1] = prefix[i] + a[i];
}
// memo 必须是 m x m,因为 left/right 最大到 m-1
vector<vector<int>> memo(m, vector<int>(m, -1));
// 先算出整个 2n 区间的所有子区间结果
dfs(a, 0, m - 1, memo, prefix);
int result = INT_MAX;
// 枚举所有长度为 len 的区间,取最小值
for (int i = 0; i < len; ++i) {
result = min(result, memo[i][i + len - 1]);
}
return result;
}
int dfs(const vector<int>& a, int left, int right,
vector<vector<int>>& memo, vector<int>& prefix) {
if (left == right) {
memo[left][right] = 0; // 注意是二维
return 0;
}
if (left > right) {
return 0;
}
if (memo[left][right] != -1) {
return memo[left][right];
}
int result = INT_MAX;
for (int i = left; i < right; ++i) {
int l = dfs(a, left, i, memo, prefix);
int r = dfs(a, i + 1, right, memo, prefix);
// 原来写成了 l + f,应该是 l + r
result = min(result, l + r + prefix[right + 1] - prefix[left]);
}
memo[left][right] = result;
return result;
}
};
cpp
class Solution {
public:
int stoneGame(vector<int> &arr) {
int n = arr.size();
if (n <= 1) return 0;
int m = 2 * n;
vector<int> a(m);
for (int i = 0; i < m; ++i) {
a[i] = arr[i % n];
}
vector<int> prefix(m + 1, 0);
for (int i = 0; i < m; ++i) {
prefix[i + 1] = prefix[i] + a[i];
}
vector<vector<int>> memo(m, vector<int>(m, -1));
int result = INT_MAX;
for (int i = 0; i < n; ++i) {
result = min(result, dfs(i, i + n - 1, memo, prefix));
}
return result;
}
int dfs(int left, int right,
vector<vector<int>>& memo,
const vector<int>& prefix) {
if (left == right) {
return 0;
}
if (memo[left][right] != -1) {
return memo[left][right];
}
int result = INT_MAX;
for (int k = left; k < right; ++k) {
int leftCost = dfs(left, k, memo, prefix);
int rightCost = dfs(k + 1, right, memo, prefix);
int mergeCost = prefix[right + 1] - prefix[left];
result = min(result, leftCost + rightCost + mergeCost);
}
memo[left][right] = result;
return result;
}
};
cpp
// 本题解信息来源于【九章算法】。请勿进行商业转载,非商业转载请注明出处。
public class Solution {
/**
* @param A an integer array
* @return an integer
*/
public int stoneGame2(int[] A) {
// Write your code here
int n = A.length;
if (n <= 1)
return 0;
int[][] dp = new int[2 * n][2 * n];
int[] sum = new int[2 * n + 1];
for (int i = 1; i <= 2 * n; ++i) {
sum[i] = sum[i - 1] + A[(i - 1) % n];
}
for (int i = 0; i < 2 * n; ++i) {
dp[i][i] = 0;
}
for(int len = 2; len <= 2 * n; ++len)
for(int i= 0;i < 2 * n && i + len - 1 < 2 * n; ++i) {
int j = i + len - 1;
dp[i][j] = Integer.MAX_VALUE;
for (int k = i; k < j; ++k) {
if (dp[i][k] + dp[k+1][j] + sum[j + 1] - sum[i] < dp[i][j])
dp[i][j] = dp[i][k] + dp[k+1][j] + sum[j + 1] - sum[i];
}
}
int ans = Integer.MAX_VALUE;
for (int i = 0; i < n; ++i)
if (dp[i][i + n - 1] < ans)
ans = dp[i][i + n - 1];
return ans;
}
}