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],我们可以枚举从左边(或者右边)取多少个数,并求枚举过程中dp[i][j]的最大值,则有状态转移方程

          dp[i][j] = sum[i][j] - Min{dp[i+1][j],dp[i+2][j],...,dp[j][j],  dp[i][i],dp[i][i+1],...,dp[i][j-1]}

      (其中sum[i][j] 表示从i到j的序列和)

例题链接:...

例题:UVa 10891

;

代码:

 1 #include "stdio.h"
 2 #include "string.h"
 3 #define N 105
 4 int a[N];
 5 int sum[N];
 6 int dp[N][N],mark[N][N];
 7
 8 int inline Min(int a,int b) { return a<b?a:b; }
 9
10 int DP(int i,int j) //记忆化搜索
11 {
12     if(mark[i][j])
13         return dp[i][j];
14     mark[i][j] = 1;
15     int m = 0;  //全部取光
16     for(int k=i+1; k<=j; k++)
17         m = Min(m,DP(k,j));
18     for(int k=j-1; k>=i; k--)
19         m = Min(m,DP(i,k));
20     dp[i][j] = sum[j] - sum[i-1] - m;
21     return dp[i][j];
22 }
23
24 int main()
25 {
26     int n;
27     int i,j,k;
28     while(scanf("%d",&n) == 1)
29     {
30         for(i=1; i<=n; i++)
31             scanf("%d",&a[i]);
32         memset(sum,0,sizeof(sum));
33         for(i=1; i<=n; i++)
34             sum[i] = sum[i-1] + a[i];
35         memset(dp,0,sizeof(dp));
36         memset(mark,0,sizeof(mark));  //标记初始化
37         printf("%d\n",2*DP(1,n)-s[n]);
38     }
39     return 0;
40 }
时间: 2024-12-18 21:50:57

09_Sum游戏(UVa 10891 Game of Sum)的相关文章

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 Game of Sum(区间博弈dp)

10891 - Game of Sum Time limit: 3.000 seconds 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

UVA 10891 Game of Sum(区间DP(记忆化搜索))

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1832 题目大意: 两个人在玩一个游戏: 给你一行n个数字,每次只能从左端或者右端取一个或多个数字. 每个人的分值就是他们各自取得的数字之和. 假设两人都足够聪明,问先手最多能比后手多多少分. 解题思路: 其实题目意思就是先手最多能得到多少分. 设dp[l][r]是取完[l,r]的

UVA 10891——Game of Sum

题目大意: 有n个数字排成一条直线,然后有两个小伙伴来玩游戏, 每个小伙伴每次可以从两端(左或右)中的任意一端取走一个或若干个数(获得价值为取走数之和), 但是他取走的方式一定要让他在游戏结束时价值尽量的高,最头疼的是两个小伙伴都很聪明,所以每一轮两人都将按照对自己最有利的方法去取数字,请你算一下在游戏结束时,先取数的人价值与后取数人价值之差(不要求绝对值). 有一个比这道题简单一点的题,是两边只能一个一个地取,做法如下: dp[i][j]表示i到j取到的最优值,用dp[i+1][j]或dp[i

UVA - 10891 —— Game of Sum

题目:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19461 这道题是一道很好的线性DP的题目,这种双头都可以选取的,可以运用带有头.尾位置信息的状态 dp[i][j] := 以第i位开头,第j位结尾的子问题的最优解 dp[i][j] = max(sum(i, i+k1) - dp[i+k1+1][j], sum(i, j-k2) - dp[i][j-k2-1])  (当 i <= j,注:i+k1 <= j &

UVA 10891 Game of Sum

题解: 这个题的题意挺误解人的. 每次选取的最优策略.我的理解每次从左开始.或从右开始.选取最大值(每个位置选取的最大值的位置是固定的).把剩下的序列给对方....但题意并不是这样 看了题解. 表示dp[ i ][ j ] 表示 区间 i j 先选得到的最大值. dp[ i ][ j ] = sum( j ) - sum( i - 1 ) - min( dp( i + 1, j ), dp( i + 2, j ), dp( i + 3, j )...dp( j ,j ), dp(  i , j

UVA - 10891 Game of Sum(记忆化搜索 dp)

#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> using namespace std; int a[100+10]; int dp[120][120]; int sum[120]; int vis[120][120]; int dfs(int f,int t) { int i,j,k; if(vis[f][t]==

UVA 10891 Game of Sum 区间dp

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19461 题目意思大致是给你一串数字,A,B两个人轮流从两端取一段数字并得到该串数字的和的点数,每个人都尽可能的多的点数,问A最多能比B多多少点. 区间dp,一开始打算分AB,但是发现太麻烦了,最后用dp(l,r)表示在区间l~r中先手能赢的的最多点数.假设A是区间(l,r)的先手的话,如果A选择了(l,k )// 或(k+1,r)的数字,那他的得分(l,r)的总分减去B在余

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 cannot take from both ends at