Uva--10891(动规 or 极大极小搜索)
2014-08-05 17:35:23
(看到网上有人用极大极小搜索 + 记忆化优化的解法,膜拜ing。。。http://www.cnblogs.com/staginner/archive/2011/12/02/2272014.html)
思路:这道题由一道经典dp题改编(原题中每次只能取一个number),这里其实也一样,就是多一个枚举某此取多少个数字的过程。
dp[i][j] 表示对于一个给定的区间[i , j],一次取能取到的最大值。sum[i][j]表示区间[i , j]内所有数的和。
dp[i][j] = sum[i][j] - min(dp[i + k][j] , dp[i][j - k]) (0 <= k <= j - i)。(k == 0时表示[i , j]区间内数全取)
1 /************************************************************************* 2 > File Name: m.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Tue 05 Aug 2014 04:55:35 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 16 int n; 17 int v[105]; 18 int dp[105][105]; 19 int sum[105]; 20 21 int main(){ 22 while(scanf("%d",&n) == 1 && n){ 23 sum[0] = 0; 24 for(int i = 1; i <= n; ++i){ 25 scanf("%d",&v[i]); 26 sum[i] = sum[i - 1] + v[i]; 27 } 28 memset(dp,0,sizeof(dp)); 29 for(int i = 1; i <= n; ++i) 30 dp[i][i] = v[i]; 31 for(int i = n; i >= 1; --i){ 32 for(int j = i + 1; j <= n; ++j){ 33 int tmin = 1e9; 34 for(int k = 1; k <= j - i; ++k){ 35 tmin = min(tmin,dp[i + k][j]); 36 tmin = min(tmin,dp[i][j - k]); 37 } 38 dp[i][j] = sum[j] - sum[i - 1] - min(tmin,dp[i][j]); 39 } 40 } 41 printf("%d\n",2 * dp[1][n] - sum[n]); 42 } 43 return 0; 44 }