题意:一排数字两个人轮流从两边拿,都采用最优策略。问先手最多能拿到多少个。
思路:dp[i][j]表示先手在i-j中最多能拿到的数字之和,然后从小到大枚举区间
状态转移:
dp[j][i+j] = max(dp[j][i+j], sum[k-1] - sum[j-1] - dp[k][i+j]);
dp[j][i+j] = max(dp[j][i+j], sum[i+j] - sum[k] - dp[j][k]);
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /************************************************** 2 * Author : xiaohao Z 3 * Blog : http://www.cnblogs.com/shu-xiaohao/ 4 * Last modified : 2014-05-06 11:34 5 * Filename : L_1031.cpp 6 * Description : 7 * ************************************************/ 8 #include <iostream> 9 #include <cstdio> 10 #include <cstring> 11 #include <cstdlib> 12 #include <cmath> 13 #include <algorithm> 14 #include <queue> 15 #include <stack> 16 #include <vector> 17 #include <set> 18 #include <map> 19 #define MP(a, b) make_pair(a, b) 20 #define PB(a) push_back(a) 21 22 using namespace std; 23 typedef long long ll; 24 typedef pair<int, int> pii; 25 typedef pair<unsigned int,unsigned int> puu; 26 typedef pair<int, double> pid; 27 typedef pair<ll, int> pli; 28 typedef pair<int, ll> pil; 29 30 const int INF = 0x3f3f3f3f; 31 const double eps = 1E-6; 32 const int LEN = 101; 33 int n, dp[LEN][LEN], num[LEN], sum[LEN]; 34 35 int main() 36 { 37 freopen("in.txt", "r", stdin); 38 39 int T, kase = 1; 40 cin >> T; 41 while(T--){ 42 cin >> n; 43 for(int i=1; i<=n; i++) 44 cin >> num[i]; 45 sum[0] = 0; 46 for(int i=1; i<=n; i++) sum[i] = sum[i-1] + num[i]; 47 for(int i=0; i<n; i++){ 48 for(int j=1; j+i<=n; j++){ 49 dp[j][i+j] = sum[i+j] - sum[j-1]; 50 for(int k=j; k<=j+i; k++){ 51 if(k!=j) 52 dp[j][i+j] = max(dp[j][i+j], sum[k-1] - sum[j-1] - dp[k][i+j]); 53 if(k!=i+j) 54 dp[j][i+j] = max(dp[j][i+j], sum[i+j] - sum[k] - dp[j][k]); 55 } 56 } 57 } 58 cout << "Case " << kase++ << ": " << dp[1][n] << endl; 59 } 60 return 0; 61 }