题意:给定一组数,每一次选手可从左右两端任意一段选取连续的任意个数,至少选一个,甲先手,保证每次最优,则最后甲比乙得分多多少。
思路:和两端取一个数字的做法差不多,即dp(i,j)表示对于从i到j的序列,先手可得得最大分,那么dp(i,j)=sum(i,j)-min{min{dp(i,k)} (k=i~j-1),min{dp(k,j) (k=i+1~j)}},注意再求最小值是因为可以把整个区间全部取走,所以记录子区间最小值的变量初始化应该为0。
#include <iostream>
#include <algorithm>
using namespace std;
int dp[110][110],s[110]={0};
int main()
{
int n;
while(cin>>n&&n){
for(int i=1;i<=n;i++) {cin>>dp[i][i];s[i]=s[i-1]+dp[i][i];}
for(int l=2;l<=n;l++)
for(int j,i=1;(j=i+l-1)<=n;i++){
int t=0;
for(int k=i;k<j;k++)
t=min(t,dp[i][k]);
for(int k=j;k>i;k--)
t=min(t,dp[k][j]);
dp[i][j]=s[j]-s[i-1]-t;
}
cout<<2*dp[1][n]-s[n]<<endl;
}
return 0;
}