#include <vector> #include <iostream> using namespace std; int win1(vector<int>& arr) {//使用标准二维dp int n = arr.size(); vector<vector<int>> first(n, vector<int>(n, 0)); //first[i][j]表示在arr[i...j]上先手获得的最好分数 vector<vector<int>> second(n, vector<int>(n, 0)); //second[i][j]表示在arr[i...j]上后手获得的最好分数 for(int i = 0; i < n; i++) { first[i][i] = arr[i]; for(int j = i-1; j >=0; j--) { //先手要么取左边的arr[j],要么取右边的aar[i],趣时主要考虑自己作为后手在剩下的局面上能拿多少分 first[j][i] = max(arr[j] + second[j+1][i], arr[i] + second[j][i-1]); //这句我花了很大心思理解,为什么是min?因为后手是被动的,只能挑先手剩下的最坏情况 second[j][i] = min(first[j+1][i], first[j][i-1]); } } return max(first[0][n-1], second[0][n-1]); } //参考:https://www.nowcoder.com/questionTerminal/19c98d950b3347d19f991d10bde12288?toCommentId=5976617 int win2(vector<int>& arr) {//使用滚动数组,压缩空间复杂度到O(n) int n = arr.size(); vector<int> first(n, 0); vector<int> second(n, 0); for(int i = 0; i < n; i++) { first[i] = arr[i]; //first[i][i] second[i] = 0; // second[i][i] 很重要,一维时需要重置,容易遗漏 for(int j = i - 1; j >= 0; j--) { int tmp = first[j]; //first[j][i-1],需要保存,因为一维时first[j]会覆盖它 first[j] = max(arr[j] + second[j+1], arr[i] + second[j]); second[j] = min(first[j+1], tmp); } } return max(first[0], second[0]); } int main() { int n; cin >> n; vector<int> arr(n); for(int i = 0; i < n; i++) { cin >> arr[i]; } //cout << win1(arr) << endl; cout << win2(arr) << endl; return 0; }