UVA 10891 Game of Sum 区间dp

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19461

题目意思大致是给你一串数字,A,B两个人轮流从两端取一段数字并得到该串数字的和的点数,每个人都尽可能的多的点数,问A最多能比B多多少点。

区间dp,一开始打算分AB,但是发现太麻烦了,最后用dp(l,r)表示在区间l~r中先手能赢的的最多点数。假设A是区间(l,r)的先手的话,如果A选择了(l,k )// 或(k+1,r)的数字,那他的得分(l,r)的总分减去B在余下区间作为先手能的到的分。
即dp(l,r) = min(sum - min(dp(l,k), dp(k+1,r)));
最终答案是A的得分减去B的得分 = 2*dp(1,n) - sum;
==>>预处理前缀和。

#include <cstring>

#include <iostream>

using namespace std;



int n;

int a[105];

int s[105];

int dp[105][105];



int DP(int l, int r) {

    if (dp[l][r] != -1) {

        return dp[l][r];

    }



    if (l == r) {

        return dp[l][r] = a[l];

    }



    int tmp = 0; 

    for (int k=l; k<r; k++) {

        tmp = min (tmp, DP(l, k));

        tmp = min (tmp, DP(k+1, r));

    }



    return dp[l][r] = s[r] - s[l-1] - tmp;

}



int main () {

    while (cin >> n) {

        if (n == 0) break;



        for (int i=1; i<=n; i++) {

            cin >> a[i];

        }

        memset(s, 0, sizeof s);

        for (int i=1; i<=n; i++) {

            s[i] = s[i-1] + a[i];

        }



        memset(dp, -1, sizeof dp);

        cout << 2 * DP(1, n) - s[n] << endl; 

    }

    return 0;

}
View Code

 

你可能感兴趣的:(game)