UVa 10891 (博弈+DP) Game of Sum
最开始的时候思路就想错了,就不说错误的思路了。
因为这n个数的总和是一定的,所以在取数的时候不是让自己尽可能拿的最多,而是让对方尽量取得最少。
记忆化搜索(时间复杂度O(n3)):
d(i, j)表示原序列中第i个元素到第j个元素构成的子序列,先手取数能够得到的最大值。
sum(i, j) 表示从第i个元素到第j个元素的和
因为要让对手获得最小的分数,所以状态转移方程为:
d(i, j) = sum(i, j) - min{d(枚举所有可能剩给对手的序列), 0(0代表全部取完)}
s数组保存a中前i个元素的和,这样sum(i, j) = s[j] - s[i-1]
#define LOCAL
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = + ;
int a[maxn], s[maxn], d[maxn][maxn], vis[maxn][maxn]; int dp(int i, int j)
{
if(vis[i][j])
return d[i][j];
vis[i][j] = ;
int m = ;
for(int k = i + ; k <= j; ++k)
m = min(m, dp(k, j));
for(int k = j - ; k >= i; --k)
m = min(m, dp(i, k));
d[i][j] = s[j] - s[i-] - m;
return d[i][j];
} int main(void)
{
#ifdef LOCAL
freopen("10891in.txt", "r", stdin);
#endif int n;
while(scanf("%d", &n) == && n)
{
s[] = ;
for(int i = ; i <= n; ++i)
{
scanf("%d", &a[i]);
s[i] = s[i-] + a[i];
}
memset(vis, , sizeof(vis));
printf("%d\n", *dp(, n) - s[n]);
}
return ;
}
代码君
递推(时间复杂度O(n2)):
令f(i, j) = min{d(i, j), d(i+1, j),,,d(j, j)}
g(i, j) = min{d(i, j), d(i, j-1),,,d(i, i)}
则状态转移方程可写成:
d(i, j) = min{f(i+1, j), g(i, j-1), 0}
f和g的递推为:
f(i, j) = min{d(i, j), f(i+1, j)}
g(i, j) = min{d(i, j), g(i, j-1)}
//#define LOCAL
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = + ;
int a[maxn], s[maxn], d[maxn][maxn], f[maxn][maxn], g[maxn][maxn]; int main(void)
{
#ifdef LOCAL
freopen("10891in.txt", "r", stdin);
#endif int n;
while(scanf("%d", &n) == && n)
{
s[] = ;
for(int i = ; i <= n; ++i)
{
scanf("%d", &a[i]);
s[i] = s[i-] + a[i];
}
for(int i = ; i <= n; ++i)//边界
d[i][i] = f[i][i] = g[i][i] = a[i];
for(int L = ; L < n; ++L)
for(int i = ; i + L <= n; ++i)
{
int j = i + L;
int m = ;
m = min(m, f[i+][j]);
m = min(m, g[i][j-]);
d[i][j] = s[j] - s[i-] - m;
//更新f和g
f[i][j] = min(d[i][j], f[i+][j]);
g[i][j] = min(d[i][j], g[i][j-]);
} printf("%d\n", *d[][n] - s[n]);
}
return ;
}
代码君
UVa 10891 (博弈+DP) Game of Sum的更多相关文章
- UVA 10891 区间DP+博弈思想
很明显带有博弈的味道.让A-B最大,由于双方都采用最佳策略,在博弈中有一个要求时,让一方的值尽量大.而且由于是序列,所以很容易想到状态dp[i][j],表示序列从i到j.结合博弈中的思想,表示初始状态 ...
- uva 10891 区间dp+记忆化搜索
https://vjudge.net/problem/UVA-10891 给定一个序列x,A和B依次取数,规则是每次只能从头或者尾部取走若干个数,A和B采取的策略使得自己取出的数尽量和最大,A是先手, ...
- 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 ...
- UVa 10891 Game of Sum (DP)
题意:给定一个长度为n的整数序列,两个人轮流从左端或者右端拿数,A先取,问最后A的得分-B的得分的结果. 析:dp[i][j] 表示序列 i~j 时先手得分的最大值,然后两种决策,要么从左端拿,要么从 ...
- UVA 10891 SUM游戏 DP
刚看到这个题目不知道怎么个DP法,有点难想到 解法如下 设置dp[i][j]代表i到j这段子序列能获得的最大值,这样,枚举m=min(m,dp[i+1到j][j],dp[i][i到j-1]),m就代表 ...
- [题解]UVa 10891 Game of Sum
在游戏的任何时刻剩余的都是1 - n中的一个连续子序列.所以可以用dp[i][j]表示在第i个数到第j个数中取数,先手的玩家得到的最大的分值.因为两个人都很聪明,所以等于自己和自己下.基本上每次就都是 ...
- 09_Sum游戏(UVa 10891 Game of Sum)
问题来源:刘汝佳<算法竞赛入门经典--训练指南> P67 例题28: 问题描述:有一个长度为n的整数序列,两个游戏者A和B轮流取数,A先取,每次可以从左端或者右端取一个或多个数,但不能两端 ...
- UVa 10891 Game of Sum - 动态规划
因为数的总和一定,所以用一个人得分越高,那么另一个人的得分越低. 用$dp[i][j]$表示从$[i, j]$开始游戏,先手能够取得的最高分. 转移通过枚举取的数的个数$k$来转移.因为你希望先手得分 ...
- hdu 4597 + uva 10891(一类区间dp)
题目链接:http://vjudge.net/problem/viewProblem.action?id=19461 思路:一类经典的博弈类区间dp,我们令dp[l][r]表示玩家A从区间[l, r] ...
随机推荐
- Asp.net的服务器推技术 (Server Push)
在以往的和服务器端通信技术中,我们多数使用的是AJAX轮询式访问,也就是在Javascript中控制时间间隔,然后每隔一段时间就访问一次服务器,然后获得数据或通知.但是这种轮询方式的访问有90%是在做 ...
- Swift 2.0 到底「新」在哪?
[编者按]2015年6月,一年一度的苹果 WWDC 大会如期而至,在大会上苹果发布了 Swift 2.0,引入了很多新的特性,以帮助开发者更快.更简单地构建应用.本篇文章作者是 Maxime defa ...
- Heroku 与 ASP.NET 5
一. Heroku 简单来讲,Heroku是一个支持多种语言.极易部署.多价位可免费的 Pass 平台,通过 Buildpack 搭建语言运行环境, 默认内建的大部分是 Web 开发中较为常见的语言, ...
- 传说中的WCF(3):多个协定
我们知道,WCF服务端是先定义服务协定,其实就是一个接口,然后通过实现接口来定义服务类.那么,有一个问题,如果一个服务类同时实现N个接口(也就是有N个协定)呢?结果会如何? 不必猜,我们还是通过实验来 ...
- iframe父子兄弟之间调用传值(contentWindow && parent)
iframe的调用包括以下几个方面:(调用包含html dom,js全局变量,js方法) 主页面调用iframe: iframe页面调用主页面: 主页面的包含的iframe之间相互调用: 主要知识点 ...
- CyclicBarrier、CountDownLatch与Semaphore的小记
CyclicBarrier: 适合的业务场景,比如 1).,现有一大任务,需要得到全年的统计数据的,这个工作量是巨大的,那么可以将其分割为12个月的子任务,各个子任务相互独立,当所有子任务完成了,则就 ...
- QScrollArea可以帮助我们实现让一个widget的内容带有滚动条(QWidget里内置QScrollArea,QScrollArea里再内置其它QWidget)
使用QScrollArea可以帮助我们实现让一个widget的内容带有滚动条,用户可以通过拖动滚动条来查看更多内容, 代码示例如下: 1.带有滚动条的widget列表 #include "w ...
- Win8.1安装VirtualSVN Server发生service visualSVN Server failed to start解决办法
Service 'VisualSVN Server' failed to start. Please check VisualSVN Server log in Event Viewer for mo ...
- OpenGL基础知识
基本概念 透视(Perspective)变换(Transformation)投影矩阵(Projection Matrix):用于将3D坐标转换为2D屏幕坐标光栅化(Rasterization): 实际 ...
- SGU 125 Shtirlits 搜索+可行性剪枝
500ms时限406ms水过…… 直接枚举肯定超时,需要剪枝. 枚举每个格子的元素,检查其左上角和正上方格子是否满足条件,若不满足不必再向下搜索. 在 这里 看到一个更好的方法: 枚举每个格子是哪个相 ...