Easy Game (区间DP)

Easy Game

LightOJ - 1031

You are playing a two player game. Initially there are n integer numbers in an array and player A and B get chance to take them alternatively. Each player can take one or more numbers from the left or right end of the array but cannot take from both ends at a time. He can take as many consecutive numbers as he wants during his time. The game ends when all numbers are taken from the array by the players. The point of each player is calculated by the summation of the numbers, which he has taken. Each player tries to achieve more points from other. If both players play optimally and player A starts the game then how much more point can player A get than player B?

Input

Input starts with an integer T (≤ 100), denoting the number of test cases.

Each case contains a blank line and an integer N (1 ≤ N ≤ 100) denoting the size of the array. The next line contains Nspace separated integers. You may assume that no number will contain more than 4 digits.

Output

For each test case, print the case number and the maximum difference that the first player obtained after playing this game optimally.

Sample Input

2

4

4 -10 -20 7

4

1 2 3 4

Sample Output

Case 1: 7

Case 2: 10

题意:有一个长度为N的整数序列,Alice和Bob轮流取数,Alice先取。每次玩家只能从左端或者右端取一个或多个数,但不能两端都取。所有数都被取走后游戏结束,然后统计每个人取走的所有数之和,作为各自的得分。两个人采取的策略都是让自己的得分尽量高,并且两个人都足够聪明。求最后结束游戏后先手和后手的得分最大差值。

题解:区间dp dp[i][j]表示的是在区间 i-j 中先手得分和后手得分的最大差值。从 i - j 遍历区间断点 k,表示在区间 [i,j] 中先手取走前 k 个,或者先手取走后 k 个所能得到的最大值。如果取走前 k 个,即先手得分为sum[k]-sum[l-1],因为先手后手都会采取最优策略,所以后手一定从剩下的区间中取走尽可能多的得分,使得差值尽可能小,那么后手的得分就是dp[k+1][r] ,同理,如果先手取走后 K 个,先手得分为sum[r]-sum[k],后手得分为dp[l][k].故dp[l][r]=max(dp[l][r],max(sum[k]-sum[l-1]-dp[k+1][r],sum[r]-sum[k]-dp[l][k]))

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define inf 0x3f3f3f3f
 6 using namespace std;
 7 int n;
 8 int a[110];
 9 int sum[110];
10 int dp[110][110];
11 int main()
12 {
13     int casen;
14     int ca=1;
15     int val;
16     cin>>casen;
17     while(casen--)
18     {
19         scanf("%d",&n);
20         memset(dp,-inf,sizeof(dp));
21         memset(sum,0,sizeof(sum));
22         for(int i=1;i<=n;i++)
23         {
24             scanf("%d",&val);
25             sum[i]=sum[i-1]+val;
26             dp[i][i]=val;
27         }
28         for(int len=2;len<=n;len++)
29         {
30             for(int l=1;l+len-1<=n;l++)
31             {
32                 int r=l+len-1;
33                 dp[l][r]=sum[r]-sum[l-1];
34                 for(int k=l;k<r;k++)
35                 {
36                     dp[l][r]=max(dp[l][r],max(sum[k]-sum[l-1]-dp[k+1][r],sum[r]-sum[k]-dp[l][k]));
37                 }
38             }
39         }
40         printf("Case %d: %d\n",ca++,dp[1][n]);
41     }
42     return 0;
43 }

emmm....莫名失眠,也算是人生第一次通宵吧,到现在竟然一点不困,神奇~希望今天明天后天大后天大大后天的所有训练对我都友好一些~体侧跑800希望不要吐出来~~

原文地址:https://www.cnblogs.com/1013star/p/10064475.html

时间: 2025-01-24 16:34:44

Easy Game (区间DP)的相关文章

Light OJ 1031 - Easy Game(区间dp)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1031 题目大意:两个选手,轮流可以从数组的任意一端取值, 每次可以去任意个但仅限在一端, 他们的得分分别是取得所有值的和.现在求这两个选手得分差值的最大值. 解题思路:设dp[i][j]代表从i到j这个区间中,所能够得到的最大差值,只需要枚举其中i到j之间的一个数c,作为断电,那么最大值应该为max(sum[c]-sum[i-1]-dp[c+1][j], sum[j]-sum

LightOJ1031 Easy Game(区间DP)

我可能真想不到这题是区间DP,不过知道是区间DP想了下就AC了. dp[i][j]表示局面为ai...aj先手能获得与后手得分的最大差值 那么转移到当前状态就是枚举中间的位置,分成两边,其中一边先手全部取另一边就是新的局面,后手变成新的先手的局面,而后手也会采取最优策略也会尽量让剩下这个局面差值最大.方程如下: dp[i][j] = max( sum[i][j] , sum[i][k]-dp[k+1][j] , sum[k+1][j]-dp[i][k] ) (i<=k<j) 1 #includ

Light OJ 1031 - Easy Game(区间DP)

题目大意: 给你一个n,代表n个数字,现在有两个选手,选手A,B轮流有有一次机会,每个选手一次可以得到一个或者多个数字,从左侧或者右侧,但是不能同时从两边取数字,当所有的数字被取完,那么游戏结束.然后计算每个选手所得到数字的总和,每个选手都尽量让自己的分数比较多,选手A先开始取数.假设每个选手取得数字都是最优的,问A最多比B多多少分数,. 题目分析: 记忆化搜索,区间DP. dp[该谁取了][左区间L][右区间] = 所能取到的最大值. 做下简单的预处理,得到区间L-R之间的和. 然后状态转移

UVA1630 Folding 区间DP

Folding Description Bill is trying to compactly represent sequences of capital alphabetic characters from `A' to `Z' by folding repeating subsequences inside them. For example, one way to represent a sequence `AAAAAAAAAABABABCCD' is `10(A)2(BA)B2(C)D

ZOJ3541:The Last Puzzle(区间DP)

There is one last gate between the hero and the dragon. But opening the gate isn't an easy task. There were n buttons list in a straight line in front of the gate and each with an integer on it. Like other puzzles the hero had solved before, if all b

UVA 10003 Cutting Sticks(区间dp)

Description  Cutting Sticks  You have to cut a wood stick into pieces. The most affordable company, The Analog Cutting Machinery, Inc. (ACM), charges money according to the length of the stick being cut. Their procedure of work requires that they onl

UVA 1331 Minimax Triangulation 区间DP

区间DP: 将一个多边形三角剖分,让可以得到的最大三角形的面积最小 dp[i][j]表示从i点到j点的最优值,枚举中间点k dp[i][j]=min(dp[i][j],max(area(i,j,k),max(dp[i][k],dp[k][j]))); 注意如果中间三角形i-j-k中有其他的点,这样的三角形是不可以剖分的 Minimax Triangulation Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld

合并沙子//区间dp

P1062 合并傻子 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 从前有一堆傻子,钟某人要合并他们~但是,合并傻子是要掉RP的...... 描述 在一个园形操场的四周站着N个傻子,现要将傻子有次序地合并成一堆.规定每次只能选相邻的2个傻子合并成新的一个傻子,并将新的一个傻子的RP数,记为该次合并的RP数.(合并方法与NOI1999石子合并(本题库的沙子合并)相同,请大家参考上题合并方法)将N个傻子合并成1个的最小RP数为RPn和最大RP数为RPx.钟

uva 10003 Cutting Sticks 简单区间dp

// uva 10003 Cutting Sticks 区间dp // 经典的区间dp // dp(i,j)表示切割小木棍i-j所需要的最小花费 // 则状态转移为dp(i,j) = min{dp(i,k) + dp(k,j) + a[j]-a[i]) // 其中k>i && k<j // a[j] - a[i] 为第一刀切割的代价 // a[0] = 0,a[n+1] = L; // dp数组初始化的时候dp[i][i+1]的值为 0,这表示 // 每一段都已经是切割了的,不