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.要看好数据范围 ...
随机推荐
- 关于HBase的概述
1.hbase的特点 ->数据存储量可以达到亿级别数据维持在秒级 ->按列存储的数据库 ->能够存储上百万列 ->hbase的底层存储依赖于HDFS ->如何扩展hbas ...
- 动态页面的登陆——装饰器应用<代码>
log_status = False f = open("info", "r", encoding="utf8") source = f.r ...
- ios9 之后,Xcode7不推荐使用UIAlertView,改用UIAlertController+UIAlertAction(按钮)
/** * ios9 之后,Xcode7不推荐使用UIAlertView,改用UIAlertController+UIAlertAction(按钮) */ UIAlertController *al ...
- windows7 密码保护 共享文件
windows7 密码保护 共享文件 2台windows7之间设置文件共享,本想使用ftp,但是配置指定用户连接,配置权限比较繁琐. 所以就想到使用window7的文件共享,并设置密码,共享整个硬盘的 ...
- c# 并行运算
c# 并行运算 1. Parallel.INVOKE() 看实例: private static Stopwatch watch = new Stopwatch(); private static v ...
- Python-S13-day2-之购物车
Python-S13-day2 需求: 1.写一个购物小程序,用户开始先输入自己的工资,然后可以不断的买东西并加入购物车,如果钱不够了提示余额不足,用户中途可以选择查看自己购物车里面的商品,以及余额, ...
- POJ2262问题描述
Goldbach's Conjecture Description In 1742, Christian Goldbach, a German amateur mathematician, sen ...
- MOGRE学习笔记(3)--MOGRE小项目练习
学习OGRE有一段时间了,领导为了检测学习效果,根据已有C++项目,弄一个类似的用c#语言编写的小项目. 配置:win7,DirectX2009,vs2010. 项目要求: 1.有Ogre窗口(尺寸1 ...
- [BS] 小知识点总结-02
1. dispatch_GCD 可让某操作延迟x秒执行 //模拟网速慢,延迟3s返回数据(就会导致右侧数据和左侧标签不对应) dispatch_after(dispatch_time(DISPATC ...
- Speed-BI 图表功能:服装订货与销售匹配分析
在作为一个买手我们根据对市场的预测,订了一批的货回来. 我们总会有一个疑问:我的订货与市场的需求是一致的吗?是否出现了较大偏差.这时我们通过分析两个指标:订货占比与销售占比的差异,进行订货与销售的匹配 ...