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 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
The input consists of a number of cases. Each case starts with a line specifying the integer n (0 < n ≤100), the number of elements in the array. After that, nnumbers are given for the game. Input is terminated by a line where n=0.
Output
For each test case, print a number, which represents the maximum difference that the first player obtained after playing this game optimally.
题目大意:给n个数,两个人轮流取数,可以从左往右或从右往左取任意多个。两个人都希望自己的取得的数的总和尽量大,都采取最优策略,问第一个人能比第二个人取得的数多多少。
思路:很容易可以想到一个$O(n^3)$的DP,用dp[i][j]代表只剩下a[i..j]的数,先手可以取得的最大值,此时后手取得的最大值为sum[i..j] - dp[i][j]。
那么状态转移方程为:dp[i][j] = max(sum[i..j], sum[i..j] - min(dp[i+1][j], dp[i+2][j]……), sum[i..j] - min(dp[i][j - 1], dp[i, j - 2])。
输出结果为2 * dp[1][n] - sum[1..n]。
代码(0.026S):
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int MAXN = ; int dp[MAXN][MAXN];
int a[MAXN], sum[MAXN];
int n; int main() {
while(scanf("%d", &n) != EOF && n) {
for(int i = ; i <= n; ++i) scanf("%d", a + i);
for(int i = ; i <= n; ++i) sum[i] = sum[i - ] + a[i];
for(int k = ; k < n; ++k) {
for(int i = ; i + k <= n; ++i) {
int j = i + k;
dp[i][j] = sum[j] - sum[i - ];
for(int p = i + ; p <= j; ++p) dp[i][j] = max(dp[i][j], sum[j] - sum[i - ] - dp[p][j]);
for(int p = j - ; p >= i; --p) dp[i][j] = max(dp[i][j], sum[j] - sum[i - ] - dp[i][p]);
}
}
printf("%d\n", * dp[][n] - sum[n]);
}
}
这个DP还有优化的余地,观察状态转移方程可以发现,dp[i][j]使用了min(dp[i+1][j], dp[i+2][j]……),而dp[i+1][j]=min(dp[i+2][j], dp[i+3][j]……),有重复的部分。
于是我们可以用l[i][j]记录max(dp[i][j], dp[i+1][j], dp[i+2][j]……),即从左往右取的后手最小值,则sum[i..j] - min(dp[i+1][j], dp[i+2][j]……)可以写成sum[i..j]-l[i+1][j]。每次更新l[i][j] = min(dp[i][j], l[i+1][j])。
同理用r[i][j]记录从右往左取的后手最小值。
至此DP优化至$O(n^2)$。
代码(0.015S):
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int MAXN = ; int dp[MAXN][MAXN];
int l[MAXN][MAXN], r[MAXN][MAXN];
int a[MAXN], sum[MAXN];
int n; int main() {
while(scanf("%d", &n) != EOF && n) {
for(int i = ; i <= n; ++i) scanf("%d", a + i);
for(int i = ; i <= n; ++i) sum[i] = sum[i - ] + a[i];
for(int k = ; k < n; ++k) {
for(int i = ; i + k <= n; ++i) {
int j = i + k;
l[i][j] = r[i][j] = dp[i][j] = sum[j] - sum[i - ];
if(i != j) {
dp[i][j] = max(dp[i][j], sum[j] - sum[i - ] - l[i + ][j]);
dp[i][j] = max(dp[i][j], sum[j] - sum[i - ] - r[i][j - ]);
l[i][j] = min(dp[i][j], l[i + ][j]);
r[i][j] = min(dp[i][j], r[i][j - ]);
}
}
}
printf("%d\n", * dp[][n] - sum[n]);
}
}
UVA 10891 Game of Sum(DP)的更多相关文章
- uva 10891 Game of Sum(区间dp)
题目连接:10891 - Game of Sum 题目大意:有n个数字排成一条直线,然后有两个小伙伴来玩游戏, 每个小伙伴每次可以从两端(左或右)中的任意一端取走一个或若干个数(获得价值为取走数之和) ...
- UVA 10891 Game of Sum(区间DP(记忆化搜索))
题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...
- UVA - 10891 Game of Sum (区间dp)
题意:AB两人分别拿一列n个数字,只能从左端或右端拿,不能同时从两端拿,可拿一个或多个,问在两人尽可能多拿的情况下,A最多比B多拿多少. 分析: 1.枚举先手拿的分界线,要么从左端拿,要么从右端拿,比 ...
- Max Sum (dp)
Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequence. F ...
- URAL 1146 Maximum Sum(DP)
Given a 2-dimensional array of positive and negative integers, find the sub-rectangle with the large ...
- UVA - 10891 Game of Sum 区间DP
题目连接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19461 Game of sum Description This ...
- HDU 1003 Max Sum(DP)
点我看题目 题意 : 就是让你从一个数列中找连续的数字要求他们的和最大. 思路 : 往前加然后再判断一下就行. #include <iostream> #include<stdio. ...
- 【UVa】Partitioning by Palindromes(dp)
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=27&page=sh ...
- 【noi 2.6_1481】Maximum sum(DP)
题意:求不重叠的2段连续和的最大值. 状态定义f[i]为必选a[i]的最大连续和,mxu[i],mxv[i]分别为前缀和后缀的最大连续和. 注意:初始化f[]为0,而max值为-INF.要看好数据范围 ...
随机推荐
- Cookie操作
1.写cookie方法 #region 登录时写入cookie public static void LoginCookieSave(string uid, string loginname, str ...
- VS小技巧
1."清理解决方案":在对程序进行分发.上传时时常需要压缩解决方案文件夹,这时如果还嫌文件太大,可以在VS里右键解决方案---清理解决方.完成后,则该解决方案下的所有项目的将所有中 ...
- 蓝牙的AVDTP协议笔记
1.概述 AVDTP(AUDIO/VIDEO DISTRIBUTION TRANSPORT PROTOCOL)是用来描述音频/视频在蓝牙设备间的传输的协议,是A2DP协议的基础协议,其在协议栈中 ...
- IOS 手势事件的冲突
关于手操作需要强调几点: UIImageView默认是不支持交互的,也就是userInteractionEnabled=NO ,因此要接收触摸事件(手势识别),必须设置userInteractionE ...
- MongoDB过过瘾
MongoDB 中默认的数据库为 test,连接后尝试以下操作 连接 插入数据:用过json的同学看到这格式相信不会陌生吧! db.person.insert({}) db.person.insert ...
- UItableView自定义标题(headerView)重用问题
在实现类似QQ列表的功能时,这样自定义了一个标题headerView 在实现类似QQ列表的功能时,这样自定义了一个标题headerView - (UIView *)tableView:(UITable ...
- php创建网站问题
网站在本地浏览的时候链接点击都提示The requested URL was not found on this server. 本地装的wamp,apache和php.ini都是好的 最后更改: 在 ...
- webView、scrollView、TableView,为了防止滚动时出现偏移,底部黑框问题等
if ([self respondsToSelector:@selector(automaticallyAdjustsScrollViewInsets)]) {self.automaticallyAd ...
- LED的压降
看具体什么LED一下是参考1.直插LED压降红:2.0-2.2V黄:1.8-2.0V绿:3.0-3.2V 额定电流约20mA. 2.贴片LED压降红:1.82-1.88V,电流5-8mA绿:1.75- ...
- iOS 开发进程与线程
进程(process)是一块包含了某些资源的内存区域.操作系统利用进程把它的工作划分为一些功能单元.进程中所包含的一个或多个执行单元称为线程(thread).进程还拥有一个私有的虚拟地址空间,该空间仅 ...