• HDU 6199gems gems gems (DP)


    gems gems gems

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 895    Accepted Submission(s): 167

    Problem Description
    Now there are n gems, each of which has its own value. Alice and Bob play a game with these n gems.
    They place the gems in a row and decide to take turns to take gems from left to right. 
    Alice goes first and takes 1 or 2 gems from the left. After that, on each turn a player can take k or k+1 gems if the other player takes k gems in the previous turn. The game ends when there are no gems left or the current player can't take k or k+1 gems.
    Your task is to determine the difference between the total value of gems Alice took and Bob took. Assume both players play optimally. Alice wants to maximize the difference while Bob wants to minimize it.
    Input
    The first line contains an integer T (1T10), the number of the test cases. 
    For each test case:
    the first line contains a numbers n (1n20000);
    the second line contains n numbers: V1,V2Vn. (100000Vi100000)
    Output
    For each test case, print a single number in a line: the difference between the total value of gems Alice took and the total value of gems Bob took.
    Sample Input
    1 3 1 3 2
    Sample Output
    4
    Source

     【题意】给一个序列,两个人玩游戏,A先手,第一次取一个或者两个数,然后轮流取,每次取得个数与前一个人相同或多一个,从左到右取,A希望差值越大,B希望差值越小,求最大差值。

    【分析】

    动规的思路考虑, dp[person][idx][k] 表示 person==1?Bob:Alice 从第 idx 个开始取,能取 k个使得结果最大(最小) 的最优答案。

    首先考虑,不考虑取的人,第 k 次最多取 k+1 个宝石。故 (k+1)(k+2)2n ,即 k 最大取值在sqrt(n*2)+1 。

    故 dp 的最大枚举状态为 2×20000×200 。

    此题的最大最小值的上下界在 INT 范围内,使用长整型会 MLE 。由于 dp[person][idx][k] 最大只与 dp[!person][idx+k][k+1] 产生联系,可用滚动数组的方式将第二维缩小。还有一种二维 做法,因为A希望自己的-B的差值大,B希望A-自己的差值小,也就是自己的-A的差值大,也就是说,两个人都希望自己的分数-对方的 结果尽量大,那么第一维就可以删掉。

    #include <bits/stdc++.h>
    #define inf 0x3f3f3f3f
    #define met(a,b) memset(a,b,sizeof a)
    #define pb push_back
    #define mp make_pair
    #define rep(i,l,r) for(int i=(l);i<=(r);++i)
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int N = 2e4+50;;
    const int M = 255;
    const int mod = 19260817;
    const int mo=123;
    const double pi= acos(-1.0);
    typedef pair<int,int>pii;
    ll qpow(int x,int qq){ll f=1,p=x;while(qq){if(qq&1)f=f*p%mod;p=1LL*p*p%mod;qq>>=1;}}
    int n,m,k;
    int dp[2][M+10][M];
    int sum[N];
    int getSum(int l,int r){return sum[r]-sum[l-1];}
    int main(){
        int T;
        scanf("%d",&T);
        while(T--){
            scanf("%d",&n);
            sum[0]=0;
            met(dp,0);
            for(int i=1,x;i<=n;i++){
                scanf("%d",&x);
                sum[i]=sum[i-1]+x;
            }
            for(int pos=n;pos;--pos){
                int maxk=int(sqrt(2*pos)+1);
                int remain=n-pos+1;
                for(int k=1;k<=min(remain,maxk);k++ ){
                    if(k==remain){
                        dp[0][pos&M][k]=getSum(pos,n);
                        dp[1][pos&M][k]=-getSum(pos,n);
                    }
                    else{
                        if(pos+k-1+k<=n){
                            dp[0][pos&M][k]=dp[1][(pos+k)&M][k];
                            dp[1][pos&M][k]=dp[0][(pos+k)&M][k];
                            if(pos+k+k+1-1<=n){
                                dp[0][pos&M][k]=min(dp[0][pos&M][k],dp[1][(pos+k)&M][k+1]);
                                dp[1][pos&M][k]=max(dp[1][pos&M][k],dp[0][(pos+k)&M][k+1]);
                            }
    
                        }
                        dp[0][pos&M][k]+=getSum(pos,pos+k-1);
                        dp[1][pos&M][k]-=getSum(pos,pos+k-1);
                    }
                }
            }
            int tmp=0;
            if(n>=1){
                tmp=dp[0][1][1];
                if(n>=2) tmp=max(tmp,dp[0][1][2]);
            }
            printf("%d
    ",tmp);
        }
        return 0;
    }
    #include <bits/stdc++.h>
    #define inf 0x3f3f3f3f
    #define met(a,b) memset(a,b,sizeof a)
    #define pb push_back
    #define mp make_pair
    #define rep(i,l,r) for(int i=(l);i<=(r);++i)
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int N = 2e4+50;;
    const int M = 255;
    const int mod = 19260817;
    const int mo=123;
    const double pi= acos(-1.0);
    typedef pair<int,int>pii;
    ll qpow(int x,int qq){ll f=1,p=x;while(qq){if(qq&1)f=f*p%mod;p=1LL*p*p%mod;qq>>=1;}}
    int n,m,k;
    int dp[N][M];
    int sum[N];
    int getSum(int l,int r){return sum[r]-sum[l-1];}
    int main(){
        int T;
        scanf("%d",&T);
        while(T--){
            scanf("%d",&n);
            sum[0]=0;
            met(dp,0);
            for(int i=1,x;i<=n;i++){
                scanf("%d",&x);
                sum[i]=sum[i-1]+x;
            }
            for(int pos=n;pos;--pos){
                int maxk=int( sqrt(2*pos)+1 );
                int remain=n-pos+1;
                for(int k=1;k<=min(remain,maxk);k++ ){
                    if(k==remain){
                        dp[pos][k]=getSum(pos,n);
                    }
                    else{
                        if(pos+k-1+k<=n){
                            dp[pos][k]=dp[pos+k][k];
                            if(pos+k+k+1-1<=n){
                                dp[pos][k]=max(dp[pos][k],dp[pos+k][k+1]);
                            }
                        }
                        dp[pos][k]=getSum(pos,pos+k-1)-dp[pos][k];
                    }
                }
            }
            int tmp=0;
            if(n>=1){
                tmp=dp[1][1];
                if(n>=2) tmp=max(tmp,dp[1][2]);
            }
            printf("%d
    ",tmp);
        }
        return 0;
    }
  • 相关阅读:
    MongoDB插入时间不正确的问题
    json 字符串转换成对象,对象转换成json字符串
    sqlServer sa用户登陆失败的解决办法
    基于web工作流开发
    javascript ajax的语法
    收藏和设为首页的方法
    asp.net收藏和设为首页的代码
    设计模式
    设计模式
    设计模式
  • 原文地址:https://www.cnblogs.com/jianrenfang/p/7507755.html
Copyright © 2020-2023  润新知