zoukankan      html  css  js  c++  java
  • (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 }
  • 相关阅读:
    安卓虚拟机adb shell sqlite3数据库
    gridview安卓实现单行多列横向滚动
    安卓gridview 网格,多行多列实现
    安卓5.0 沉浸式状态栏
    Acionbar logo
    .replace(R.id.container, new User()).commit();/The method replace(int, Fragment) in the type FragmentTransaction is not app
    导航抽屉图标+文字
    透明ActionBar
    去掉Actionbar下的shadow
    沉浸式导航栏
  • 原文地址:https://www.cnblogs.com/quintessence/p/7504089.html
Copyright © 2011-2022 走看看