思路
就像提示里说的,该问题实际上可以描述为,给N个数,从里面选择N/3个数使其和最大,选出的数不能相邻,且不能同时选第一个和最后一个。
如果没有最后一个限制条件的话,其实就是个背包问题,定义dp[i][j] = [0~i]选j个数的最大和
,然后能够得到dp[i][j] = max(dp[i - 1][j], dp[i - 2][j - 1] + slices[i])
,也就是计算dp[i][j]
的时候需要考虑是否选slices[i]
的问题。
然后对于第一个和最后一个不能同时选的问题,可以这么思考:因为不能同时选slices[0]
和slices[n - 1]
,所以最终解要么是在[0~n-2]
中,要么是在[1~n-1]
中,所以两遍dp,一次只dp前n-1个,一次只dp后n-1个,然后取最大值即可
代码
class Solution {
public:
int maxSizeSlices(vector<int> &slices) {
const int sz = (int)slices.size();
vector<vector<int>> dp1(sz, vector<int>(sz / 3 + 1, 0));
dp1[0][1] = slices[0];
dp1[1][1] = max(slices[0], slices[1]);
for (int i = 2; i < sz - 1; i++) {
dp1[i][1] = max(dp1[i - 1][1], slices[i]);
for (int j = 1; j <= i && j <= sz / 3; j++) {
dp1[i][j] = max(dp1[i - 1][j], dp1[i - 2][j - 1] + slices[i]);
}
}
vector<vector<int>> dp2(sz, vector<int>(sz / 3 + 1, 0));
dp2[1][1] = slices[1];
for (int i = 2; i < sz; i++) {
dp2[i][1] = max(dp2[i - 1][1], slices[i]);
for (int j = 1; j <= i && j <= sz / 3; j++) {
dp2[i][j] = max(dp2[i - 1][j], dp2[i - 2][j - 1] + slices[i]);
}
}
return max(dp1[sz - 2][sz / 3], dp2[sz - 1][sz / 3]);
}
};