HDU 6199 2017沈阳网络赛 DP

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6199

题意:n堆石子,Alice和Bob来做游戏,一个人选择取K堆那么另外一个人就必须取k堆或者k+1堆,两个人都想使用最优策略使得取出的石子的和的差值最大。

解法:http://blog.csdn.net/DorMOUSENone/article/details/77929439 膜大牛 用动态规划的思路来思考,每个人都想最大化自己和另外一个人的差值,其实这个题,完全可以省掉判断是谁的这一维,使得整个转移变得简单。dp[i][j]表示当前人从i开始取数取j个的最大差值。转移为:dp[i][k] = sum[i+j-1]-sum[i-1]-max(dp[i+j][j], dp[i+j][j+1])。从后往前转移,注意下标越界的问题。

 

#include <bits/stdc++.h>
using namespace std;
const int maxn = 20010;
//dp[i][j]表示当前这个人i从取数,取j个的最大值
//dp[i][j]=sum[i+j-1]-sum[i-1]-max(dp[i+j][j],dp[i+j][j+1])
//ans=max(dp[1][1],dp[1][2])
int a[maxn], dp[maxn][210], sum[maxn];
int main()
{
    int T, n;
    scanf("%d", &T);
    while(T--){
        scanf("%d", &n);
        for(int i=1; i<=n; i++) scanf("%d", &a[i]), sum[i]=sum[i-1]+a[i];
        int ans = -0x3f3f3f3f;
        for(int i=n; i>=1; i--){
            for(int j=min(200,n-i+1); j>=1; j--){
                dp[i][j] = sum[i+j-1]-sum[i-1];
                if(n-i-j+1>=j){
                    int ret = dp[i+j][j];
                    if(n-i-j>=j){
                        ret = max(ret, dp[i+j][j+1]);
                    }
                    dp[i][j] -= ret;
                }
                if(i==1 && j<=2) ans = max(dp[i][j], ans);
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

 

posted @ 2017-09-15 09:48  zxycoder  阅读(234)  评论(0编辑  收藏  举报