• (dp)HDU6199- gems gems gems


    gems gems gems

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


    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
     

     dp[i][j]表示以第i个数开始,当前先手选择连续j个的最大差值。无需考虑具体是哪个人操作,每个人都希望到自己时自己的值与对方的值差尽可能的大,故只需开二维即可。

    转移方程为 dp[i][j]=min(-dp[i+j][j]+sum[i+j-1]-sum[i-1],-dp[i+j][j+1]+sum[i+j-1]-sum[i-1]) 其中有几个细节,一是如果i+j-1==n,则当前先手只有唯一选择dp[i][j]=sum[n]-sum[i-1] ,二是若i+j-1>n,则不存在(i,j)状态下先手的任何状态,三是递推时要保证 (i+j,j) (i+j,j+1)如果算在转移中,一定要保证其为可行的先手状态。

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <algorithm>
      4 #include <vector>
      5 #include <set>
      6 #include <map>
      7 #include <string>
      8 #include <cstring>
      9 #include <stack>
     10 #include <queue>
     11 #include <cmath>
     12 #include <ctime>
     13 #include <bitset>
     14 #include <utility>
     15 #include <assert.h>
     16 using namespace std;
     17 #define rank rankk
     18 #define mp make_pair
     19 #define pb push_back
     20 #define xo(a,b) ((b)&1?(a):0)
     21 #define tm tmp
     22 //#define LL ll
     23 typedef unsigned long long ull;
     24 typedef pair<int,int> pii;
     25 typedef long long ll;
     26 typedef pair<ll,int> pli;
     27 typedef pair<ll,ll> pll;
     28 const int INF=0x3f3f3f3f;
     29 const ll INFF=0x3f3f3f3f3f3f3f3fll;
     30 const int MAX=2e6+5;
     31 const ll MAXN=2e8;
     32 const int MAX_N=MAX;
     33 const double da=2e9+5.0;
     34 const ll MOD=998244353;
     35 //const long double pi=acos(-1.0);
     36 //const double eps=0.00000001;
     37 int gcd(int a,int b){return b?gcd(b,a%b):a;}
     38 template<typename T>inline T abs(T a) {return a>0?a:-a;}
     39 template<class T> inline
     40 void read(T& num) {
     41     bool start=false,neg=false;
     42     char c;
     43     num=0;
     44     while((c=getchar())!=EOF) {
     45         if(c=='-') start=neg=true;
     46         else if(c>='0' && c<='9') {
     47             start=true;
     48             num=num*10+c-'0';
     49         } else if(start) break;
     50     }
     51     if(neg) num=-num;
     52 }
     53 inline ll powMM(ll a,ll b,ll M){
     54     ll ret=1;
     55     a%=M;
     56 //    b%=M;
     57     while (b){
     58         if (b&1) ret=ret*a%M;
     59         b>>=1;
     60         a=a*a%M;
     61     }
     62     return ret;
     63 }
     64 void open()
     65 {
     66 //    freopen("1009.in","r",stdin);
     67     freopen("out.txt","w",stdout);
     68 }
     69 ll dp[20005][150],sum[20005];
     70 int t,n,st;
     71 int main()
     72 {
     73     scanf("%d",&t);
     74     while(t--)
     75     {
     76         scanf("%d",&n);
     77         for(int i=1;i<=n;i++)scanf("%lld",&sum[i]),sum[i]+=sum[i-1];
     78         for(int i=1;i<=n;i++)
     79         {
     80             st=(int)ceil((sqrt(1.0+8.0*i)-1.0)/2.0)+1;
     81             for(int j=1;j<=st;j++)
     82                 dp[i][j]=INFF/2LL;
     83         }
     84         for(int i=n;i>=1;i--)
     85         {
     86             st=(int)ceil((sqrt(1.0+8.0*i)-1.0)/2.0)+1;
     87             for(int j=st;j>=1;j--)
     88             {
     89                 if(i+j-1==n)
     90                     dp[i][j]=sum[i+j-1]-sum[i-1];//选择唯一
     91                 else if(i+j-1>n)
     92                     dp[i][j]=INFF/2LL;//不存在
     93                 else
     94                 {
     95                     if(dp[i+j][j]==INFF/2LL&&dp[i+j][j]==INFF/2LL)dp[i][j]=sum[i+j-1]-sum[i-1];
     96                     else if(dp[i+j][j+1]==INFF/2LL)dp[i][j]=-dp[i+j][j]+sum[i+j-1]-sum[i-1];
     97                     else dp[i][j]=min(-dp[i+j][j]+sum[i+j-1]-sum[i-1],-dp[i+j][j+1]+sum[i+j-1]-sum[i-1]);//枚举后手的选择
     98                 }
     99             }
    100         }
    101         if(n==1)printf("%lld
    ",dp[1][1]);
    102         else printf("%lld
    ",max(dp[1][1],dp[1][2]));
    103     }
    104 }
  • 相关阅读:
    Manjaro配置攻略
    Manjaro蓝牙连接问题
    清除所有分区的根目录下的存在隐藏对系统不利的代码的文件
    取消默认磁盘共享
    高手必读 网络端口安全防护技巧放送
    批处理设置虚拟内存
    批处理方式修改IP地址和电脑名
    c++的基本知识
    Windows线程同步与互斥技术总结
    批处理方式设置XP系统的服务程序
  • 原文地址:https://www.cnblogs.com/quintessence/p/7504089.html
Copyright © 2020-2023  润新知