题意:
有一列数...A,B分别来取..每次只能从两头中一头开始拿走若干个..问最后A拿走的数比B拿走的大多少...
题解:
首先能想到是区间DP的问题...对于一个区间..感觉上是可以通过其子区间推出最优解的..
dp [ i ] [ j ] 代表在i,j区间能取得的最大值...
那么有 dp [ i ] [ j ] = sum [ i ] [ j ] - min ( dp [ i ] [ k ] , dp [ k ] [ j ] ) , ( i<=k<=j )
最后得出dp[ 1 ] [ n ] 代表了A能拿的最大价值.那么题目所需要的答案为 ans = dp[ 1 ] [n ] - ( sum [ 1 ] [ n ] - dp [ 1 ] [ n ] )
总结
所有的DP问题都可以用两种大方向来写: 1、递推 2、记忆化搜索
记忆化搜索的好处是十分直观....特别是对于树形DP和区间DP这类型的问题.
Program:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<algorithm>
#define ll long long
#define oo 1000000007
#define pi acos(-1.0)
#define MAXN 105
using namespace std;
int n,sum[MAXN],dp[MAXN][MAXN];
bool used[MAXN][MAXN];
void dfs(int s,int e)
{
if (s>e) return;
if (used[s][e]) return;
used[s][e]=true;
dp[s][e]=-oo;
int S=sum[e]-sum[s-1];
for(int k=1;k<=e-s+1;k++)
{
dfs(s+k,e),dfs(s,e-k);
dp[s][e]=max(dp[s][e],S-min(dp[s+k][e],dp[s][e-k]));
}
return;
}
int main()
{
while (~scanf("%d",&n) && n)
{
int i,x;
sum[0]=0;
for (i=1;i<=n;i++)
{
scanf("%d",&x);
sum[i]=sum[i-1]+x;
dp[i][i]=x;
}
memset(used,false,sizeof(used));
dfs(1,n);
printf("%d\n",dp[1][n]-(sum[n]-dp[1][n]));
}
return 0;
}