zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    IIS7.5解决应用程序池回收假死问题
    SQLServer跨库查询--分布式查询(转载)
    解决:System.Data.SqlClient.SqlError: FILESTREAM 功能被禁用
    Silverlight:telerik RadControls中RadGridView的一个Bug及解决办法(转载)
    list如何remove
    2015-11-18看的几篇文章,还没看完,先记录一下,回家看
    详解Android中AsyncTask的使用
    [Android] 随时拍图像处理部分总结及源码分享
    [Android] 通过GridView仿微信动态添加本地图片
    Android5.0以上系统的移动网络开关
  • 原文地址:https://www.cnblogs.com/jianrenfang/p/7507755.html
Copyright © 2011-2022 走看看