leedcode-1563. 石子游戏 V
思路一:(区间dp)
dp[i][j] 表示合并区间 i ~ j 所能获得的最大收益
class Solution { public: int a[505]; int dp[505][505]; int stoneGameV(vector<int>& stoneValue) { int len = stoneValue.size(); for(int i = 1; i <= len; i++) { a[i] = stoneValue[i-1]; a[i] += a[i-1]; } for(int ls = 2; ls <= len; ls++){ // 长度 for(int i = 1; i <= len; i++) { // 左端 int j = i + ls - 1; //右端 if (j > len) break; for(int k = i; k < j; k++){ int sum_l = a[k] - a[i-1]; int sum_r = a[j] - a[k]; if (sum_l > sum_r) dp[i][j] = max(dp[i][j], dp[k+1][j] + sum_r); else if (sum_l < sum_r) dp[i][j] = max(dp[i][j], dp[i][k] + sum_l); else dp[i][j] = max(dp[i][j], max(dp[i][k]+sum_l, dp[k+1][j]+sum_r)); } } } return dp[1][len]; } };
思路二:(记忆化搜索)
class Solution { public: int sum[505]; int dp[505][505]; int dfs(int l, int r){ if (l >= r) return 0; if (dp[l][r]) return dp[l][r]; int ans = 0; for(int i = l; i < r; i++){ int s1 = sum[i]-sum[l-1]; int s2 = sum[r]-sum[i]; if(s1 < s2) ans = max(ans, s1 + dfs(l, i)); else if (s1 > s2) ans = max(ans, s2 + dfs(i+1, r)); else ans = max(ans, max(dfs(l, i), dfs(i+1, r))+s1); } return dp[l][r] = ans; } int stoneGameV(vector<int>& stoneValue) { sum[1] = stoneValue[0]; for(int i = 1; i < stoneValue.size(); i++) { sum[i+1] = sum[i] + stoneValue[i]; } int len = stoneValue.size(); return dfs(1, len); } };
东北日出西边雨 道是无情却有情