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;
}

 
posted @ 2016-09-05 20:55  kiuhghcsc  阅读(112)  评论(0编辑  收藏  举报