Light OJ 1031: Easy Game 区间DP
Easy Game
题目链接:
http://www.lightoj.com/volume_showproblem.php?problem=1031
题意:
给出一个含n个数的序列(n≤100),A和B每次能从这个序列的左端或右端取任意个数,这两个人很聪明,每次都会取对自己最优的情况(自己取得的数的和就是获得的分数,要使分数尽可能比对方的大),现在由A先开始取,求A的分数-B的分数的最大值。
题解:
有点博弈的感觉在里边,设dp[i,j]为区间[i,j]的最大值,则可以在[i,j]内取一个值k,使A先取k~j的所有值或者i~k的所有值,则dp[i][j]=max(dp[i][j],sum[j]-sum[k-1]-dp[i][k-1]),sum[j]-sum[k-1]-dp[i][k-1])),假设A先取了k~j的所有值 则此时答案为sum[k~j]-剩余区间中B可以得到的最优情况,同理得A先取i~k时的答案
代码
#include<stdio.h>
#include<string.h>
#define Type int
#include<algorithm>
using namespace std;
const int N=101;
Type dp[N][N],sum[N],a[N];
Type mmax(Type x,Type y)
{
return x>y?x:y;
}
void clean()
{
for(int i=1;i<=100;++i)
for(int j=1;j<=100;++j)
dp[i][j]=(i>j?0:-999999999);
sum[0]=0;
}
void solve()
{
int n,T,w=0;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
clean();
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i]);
dp[i][i]=a[i];
sum[i]=sum[i-1]+a[i];
}
for(int len=1;len<=n;++len)
for(int i=1;i+len<=n;++i)
{
int j=i+len;
for(int k=i;k<=j;++k)
{
dp[i][j]=mmax(dp[i][j],sum[k]-sum[i-1]-dp[k+1][j]);
dp[i][j]=mmax(dp[i][j],sum[j]-sum[k-1]-dp[i][k-1]);
}
}
printf("Case %d: %d\n",++w,dp[1][n]);
}
}
int main()
{
solve();
return 0;
}