(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 (1≤T≤10), the number of the test cases. 
For each test case:
the first line contains a numbers n (1≤n≤20000);
the second line contains n numbers: V1,V2…Vn. (?100000≤Vi≤100000)

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\n",dp[1][1]);
102         else printf("%lld\n",max(dp[1][1],dp[1][2]));
103     }
104 }
时间: 2024-10-12 03:36:11

(dp)HDU6199- gems gems gems的相关文章

hdu 5623 KK&#39;s Number(dp)

问题描述 我们可爱的KK有一个有趣的数学游戏:这个游戏需要两个人,有N\left(1\leq N\leq 5*{10}^{4} \right)N(1≤N≤5∗10?4??)个数,每次KK都会先拿数.每次可以拿任意多个数,直到NN个数被拿完.每次获得的得分为取的数中的最小值,KK和对手的策略都是尽可能使得自己的得分减去对手的得分更大.在这样的情况下,最终KK的得分减去对手的得分会是多少? 输入描述 第一行一个数T\left( 1\leq T\leq 10\right)T(1≤T≤10),表示数据组

Ural 1353 Milliard Vasya&#39;s Function(DP)

题目地址:Ural 1353 定义dp[i][j],表示当前位数为i位时,各位数和为j的个数. 对于第i位数来说,总可以看成在前i-1位后面加上一个0~9,所以状态转移方程就很容易出来了: dp[i][j]=dp[i][j]+dp[i][j-1]+dp[i][j-2]+.......+dp[i][j-9]: 最后统计即可. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <

HDU 4908 (杭电 BC #3 1002题)BestCoder Sequence(DP)

题目地址:HDU 4908 这个题是从m开始,分别往前DP和往后DP,如果比m大,就比前面+1,反之-1.这样的话,为0的点就可以与m这个数匹配成一个子串,然后左边和右边的相反数的也可以互相匹配成一个子串,然后互相的乘积最后再加上就行了.因为加入最终两边的互相匹配了,那就说明左右两边一定是偶数个,加上m就一定是奇数个,这奇数个的问题就不用担心了. 代码如下: #include <iostream> #include <stdio.h> #include <string.h&g

Sicily 1146:Lenny&#39;s Lucky Lotto(dp)

题意:给出N,M,问有多少个长度为N的整数序列,满足所有数都在[1,M]内,并且每一个数至少是前一个数的两倍.例如给出N=4, M=10, 则有4个长度为4的整数序列满足条件: [1, 2, 4, 8], [1, 2, 4, 9], [1, 2, 4, 10], [1, 2, 5, 10] 分析:可用动态规划解题,假设dp[i][j],代表满足以整数i为尾数,长度为j的序列的个数(其中每一个数至少是前一个数的两倍).那么对于整数i,dp[i][j] 等于所有dp[k][j-1]的和,其中k满足:

UVA542 - France &#39;98(dp)

UVA542 - France '98(dp) 题目链接 题目大意:之前题目意思还以为看懂了,其实没看明白,它已经把各个选手分在各自所在的区域里面,这就意味着第一次的PK的分组已经确定,而且冠军必须是从两个左右分区出来的胜利者才有机会pk冠军. 解题思路:那么从1-16这个大的区间内诞生出来的冠军可能是来自左边,也可能是右边,然后再左边右边的子区间递归找出冠军.f[i][l][r]表示l-r这个区间的胜利者是i的概率,那么假设i在区间的最左边,f[i][l][r] = Sum(f[i][l][m

HDU 4968 Improving the GPA(dp)

HDU 4968 Improving the GPA 题目链接 dp,最大最小分别dp一次,dp[i][j]表示第i个人,还有j分的情况,分数可以减掉60最为状态 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int t, avg, n; double dp1[15][405], dp2[15][405]; double get(int x) { if

URAL 1167. Bicolored Horses (DP)

题目链接 题意 :农夫每天都会放马出去,然后晚上把马赶入马厩,于是让马排成一行入马厩,但是不想马走更多的路,所以让前p1匹入第一个马厩,p2匹马入第二个马厩…………但是他不想让他的任何一个马厩空着,所有的马都必须入马厩.有两种颜色的马,如果 i 匹黑马与 j 匹白马同在一个马厩,不愉快系数是 i * j,总系数就是k个系数相加.让总系数最小. 思路 : dp[i][j] 代表的是前 i 个马厩放 j 匹马的最小不愉快系数值. 1 //1167 2 #include <cstdio> 3 #in

2014多校第七场1005 || HDU 4939 Stupid Tower Defense (DP)

题目链接 题意 :长度n单位,从头走到尾,经过每个单位长度需要花费t秒,有三种塔: 红塔 :经过该塔所在单位时,每秒会受到x点伤害. 绿塔 : 经过该塔所在单位之后的每个单位长度时每秒都会经受y点伤害. 蓝塔 : 经过该塔所在单位之后,再走每个单位长度的时候时间会变成t+z. 思路 : 官方题解 : 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #define LL long long

hdu4939 Stupid Tower Defense (DP)

2014多校7 第二水的题 4939 Stupid Tower Defense Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 366    Accepted Submission(s): 88 Problem Description FSF is addicted to a stupid tower defense game.

Codeforces Round #260 (Div. 1) A. Boredom (DP)

题目链接:http://codeforces.com/problemset/problem/455/A A. Boredom time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Alex doesn't like boredom. That's why whenever he gets bored, he comes up with