首页 > 代码库 > Light OJ 1031 - Easy Game(区间dp)

Light OJ 1031 - Easy Game(区间dp)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1031

题目大意:两个选手,轮流可以从数组的任意一端取值, 每次可以去任意个但仅限在一端, 他们的得分分别是取得所有值的和。现在求这两个选手得分差值的最大值。

解题思路:设dp[i][j]代表从i到j这个区间中,所能够得到的最大差值,只需要枚举其中i到j之间的一个数c,作为断电,那么最大值应该为max(sum[c]-sum[i-1]-dp[c+1][j], sum[j]-sum[c-1]-cou(i, c-1))。然后在更新这一个值就行了。

代码如下:

技术分享
#include <bits/stdc++.h>

using namespace std;
const int N = 107;
int sum[N], dp[N][N];

int cou(int i, int j)
{
    if(i > j)
        return 0;

    if(dp[i][j] != INT_MAX)
        return dp[i][j];

    dp[i][j] = sum[j] - sum[i-1];
    for(int c=i; c<=j; ++ c)
    {
        dp[i][j] = max(dp[i][j], sum[c] - sum[i-1] - cou(c+1, j));
        dp[i][j] = max(dp[i][j], sum[j] - sum[c-1] - cou(i, c-1));
    }

    return dp[i][j];
}

void solve(int cases)
{
    int n;
    scanf("%d", &n);

    for(int i=1; i<=n; ++ i)
        for(int j=1; j<=n; ++ j)
            dp[i][j] = INT_MAX;

    sum[0] = 0;
    for(int i=1; i<=n; ++ i)
    {
        scanf("%d", &sum[i]);
        dp[i][i] = sum[i];
        sum[i] += sum[i-1];
    }
    printf("Case %d: %d\n", cases, cou(1, n));
}
int main()
{
    int t;
    scanf("%d", &t);
    for(int i=1; i<=t; ++ i)
        solve(i);
    return 0;
}
View Code

 

Light OJ 1031 - Easy Game(区间dp)