UVa 10891 Sum游戏

https://vjudge.net/problem/UVA-10891

题意:

有一个长度为n的整数序列,两个游戏者A和B轮流取数,A先取。每次玩家只能从左端或者右端取任意数量个数,但不能两端都取。所有数都被取走后游戏结束,然后统计每个人取走的所有数之和,作为各自的得分。两个人采取的策略都是让自己的得分尽量高,并且两个人都足够聪明,求A的得分减去B的得分后的结果。

思路:

不管是轮到谁取数,都是在一个序列中从左边或右边开始取最大值。

那么我们就令d【i】【j】表示先手在【i~j】序列中所能取到的最大值。

状态转移时,枚举从左端开始取k个数和从右端开始取k个数即可。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<sstream>
 6 #include<vector>
 7 #include<stack>
 8 #include<queue>
 9 #include<cmath>
10 #include<map>
11 using namespace std;
12 typedef long long LL;
13 typedef pair<int,int> pll;
14 const int INF=0x3f3f3f3f;
15 const int maxn=100+5;
16
17 int n;
18 int a[maxn];
19 int sum[maxn];
20 int vis[maxn][maxn];
21 int d[maxn][maxn];
22
23 int dp(int i,int j)
24 {
25     if(vis[i][j])  return d[i][j];
26     vis[i][j]=1;
27
28     int m=0;
29     for(int k=i+1;k<=j;k++)  m=min(m,dp(k,j));
30     for(int k=j-1;k>=i;k--)  m=min(m,dp(i,k));
31     d[i][j]=sum[j]-sum[i-1]-m;
32     return d[i][j];
33 }
34
35 int main()
36 {
37     //freopen("D:\\input.txt","r",stdin);
38     while(~scanf("%d",&n) && n)
39     {
40         sum[0]=0;
41         for(int i=1;i<=n;i++)
42         {
43             scanf("%d",&a[i]);
44             sum[i]=sum[i-1]+a[i];
45         }
46
47         memset(vis,0,sizeof(vis));
48         printf("%d\n",2*dp(1,n)-sum[n]);
49     }
50     return 0;
51 }
时间: 2024-08-06 18:50:03

UVa 10891 Sum游戏的相关文章

uva 10891 sum游戏(区间dp)

 给定n个数字,A和B可以从这串数字的两端任意选数字,一次只能从一端选取.并且A B都尽力使自己选择的结果为最大的,可以理解成A B每一步走的都是最优的.如果A先选择,则A B差值最大是多少. 思路:用d[i][j]表示当前选手先手走能获得的最大总分数,由于总的分数是一定的,那么状态转移方程为 d[i][j] = sum(i, j) - min( minleft(i+1, j), minright(i, j-1), 0) 其中minleft(i, j)表示min(d[i][j], d[i+1

09_Sum游戏(UVa 10891 Game of Sum)

问题来源:刘汝佳<算法竞赛入门经典--训练指南> P67 例题28: 问题描述:有一个长度为n的整数序列,两个游戏者A和B轮流取数,A先取,每次可以从左端或者右端取一个或多个数,但不能两端都取,所有数都被取完时游戏结束,然后统计每个人取走的所有数字之和作为得分,两人的策略都是使自己的得分尽可能高,并且都足够聪明,求A的得分减去B的得分的结果. 问题分析:1.设dp[i][j]表示从第i到第j的数的序列中,双方都采取最优策略的前提下,先手得分的最大值 2.若求dp[i][j],我们可以枚举从左边

uva 10891 Game of Sum (DP)

uva 10891 Game of Sum (DP) This is a two player game. Initially there are n integer numbers in an array and players 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 ca

UVa 10891 (博弈+DP) Game of Sum

最开始的时候思路就想错了,就不说错误的思路了. 因为这n个数的总和是一定的,所以在取数的时候不是让自己尽可能拿的最多,而是让对方尽量取得最少. 记忆化搜索: d(i, j)表示原序列中第i个元素到第j个元素构成的子序列,先手取数能够得到的最大值. sum(i, j) 表示从第i个元素到第j个元素的和 因为要让对手获得最小的分数,所以状态转移方程为: d(i, j) = sum(i, j) - min{d(枚举所有可能剩给对手的序列), 0(0代表全部取完)} s数组保存a中前i个元素的和,这样s

UVA 1210 Sum of Consecutive Prime Numbers(数论)

UVA - 1210 Sum of Consecutive Prime Numbers Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Some positive integers can be represented by a sum of one or more consecutive prime numbers. How many such

uva 10290 {Sum+=i++} to Reach N (数论-整数和素数)

Problem H {sum+=i++} to Reach N Input: standard input Output:  standard output Memory Limit: 32 MB All the positive numbers can be expressed as a sum of one, two or more consecutive positive integers. For example 9 can be expressed in three such ways

UVA 766 - Sum of powers(伯努利数)

766 - Sum of powers 题意:求    转化成 的各系数 思路:在wiki看了伯努利数的性质,  可以推成 . 然后B为伯努利数,有公式, 如此一来就可以去递推求出每项伯努利数了,然后在根据n去通分,求出每一项的答案,中间过程用到了分数的运算. 代码: #include <stdio.h> #include <string.h> long long gcd(long long a, long long b) { if (!b) return a; return gc

uva 766 - Sum of powers(数学+递推)

题目连接:uva 766 - Sum of powers 题目大意:将Sk(n)=∑i=1nik化简成Sk(n)=ak+1nk+1+aknk+?+a0M 解题思路: 已知幂k,并且有(n+1)k=C(kk)nk+C(k?1k)nk?1+?+C(0k)n0结论. 所以令 (n+1)k+1?nk+1=C(kk+1)nk+C(k?1k+1)nk?1+?+C(0k+1)n0 nk+1?(n?1)k+1=C(kk+1)(n?1)k+C(k?1k+1)(n?1)k?1+?+C(0k+1)(n?1)0 - 2

[动态规划] Sum游戏 ( Game of Sum, Uva 10891 )

抓住状态转移方程即可   :  从子序列 i j 中取最大 =  i + 从子序列i+1,j中取最大        或         j +  从子序列i,j-1中取最大 #include <algorithm> #include <cstring> #include <cstdio> using namespace std; const int maxn = 100+10; int S[maxn], A[maxn], d[maxn][maxn], vis[maxn]