传送门

Description

给定一个长为n的整数序列,由A和B轮流取数(A先取)。每个人可从序列的左端或右端取若干个数(至少一个),但不能两端都取。所有数都被取走后,两人分别统计所取数的和作为各自的得分。假设A和B都足够聪明,都使自己得分尽量高,求A的最终得分。

Input

第一行,一个正整数T,表示有T组数据。

接着T行,每行第一个数为n,接着n个整数表示给定的序列.

Output

输出T行,每行一个整数,表示A的得分

Sample Input

2
1 -1
2 1 2

Sample Output

-1
3

Hint

时限3s。

对于100%的数据,\(n \leq 1000, T \leq 100\)

Solution

显然是博弈DP。考虑设\(f_{i,j}\)是区间\([i,j]\)先手取数的最大答案。转移显然为

\(f_{i,j}=sum_j-sum_i-min{f_{k,j},f_{i,k}}\),其中满足\(i~<~k~<~j\)。枚举\(k\)进行转移,复杂度是\(O(n^3)\)。直接凉凉。

状态已经是\(O(n^2)\)无法优化。考虑对转移进行优化。考虑枚举\(k\)是求一定区间内\(f\)的最大值。这个\(f\)的区间是从小到大枚举的,所以可以维护区间内\(f\)的最大值。具体的,设\(l_{i,j}\)代表\(max{f_{i,k}}\),\(r_{i,j}\)代表\(max{f_{k,r}}\),其中满足\(i~<~k~<~j\)。

这样转移方程就变成\(f_{i,j}=sum_j-sum_i-min{l_{i,j},r_{i,j}}\)。这样使用DP对DP进行优化,转移变成\(O(1)\)的,可以通过本题。

其中\(l_{i,j}=max{l_{i,j-1},f_{i,j}}\),\(r\)的转移同理。

Code

#include<cstdio>
#include<cstring>
#define rg register
#define ci const int
#define cl const long long int typedef long long int ll; namespace IO {
char buf[50];
} template<typename T>
inline void qr(T &x) {
char ch=getchar(),lst=' ';
while(ch>'9'||ch<'0') lst=ch,ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
if (lst=='-') x=-x;
} template<typename T>
inline void write(T x,const char aft,const bool pt) {
if(x<0) {putchar('-');x=-x;}
int top=0;
do {
IO::buf[++top]=x%10+'0';
x/=10;
} while(x);
while(top) putchar(IO::buf[top--]);
if(pt) putchar(aft);
} template <typename T>
inline T mmax(const T a,const T b) {if(a>b) return a;return b;}
template <typename T>
inline T mmin(const T a,const T b) {if(a<b) return a;return b;}
template <typename T>
inline T mabs(const T a) {if(a<0) return -a;return a;} template <typename T>
inline void mswap(T &a,T &b) {T temp=a;a=b;b=temp;} const int maxn = 1010; int t,n;
int MU[maxn],frog[maxn][maxn],lmax[maxn][maxn],rmax[maxn][maxn],sum[maxn]; void clear(); int main() {
qr(t);
while(t--) {
clear() ;
qr(n);
for(rg int i=1;i<=n;++i) qr(MU[i]);
for(rg int i=1;i<=n;++i) lmax[i][i]=rmax[i][i]=frog[i][i]=MU[i],sum[i]=sum[i-1]+MU[i];
for(rg int i=1;i<n;++i) {
for(rg int j=1;j<n;++j) {
rg int r=i+j;if(r>n) break;
frog[j][r]=sum[r]-sum[j-1]-mmin(0,mmin(lmax[j][r-1],rmax[j+1][r]));
lmax[j][r]=mmin(frog[j][r],lmax[j][r-1]);rmax[j][r]=mmin(frog[j][r],rmax[j+1][r]);
}
}
write(frog[1][n],'\n',true);
}
return 0;
} void clear() {
memset(MU,0,sizeof MU);
memset(sum,0,sizeof sum);
memset(frog,0,sizeof frog);
memset(lmax,0,sizeof lmax);
memset(rmax,0,sizeof rmax);
n=0;
}

Summary

在DP因为复杂度较高而无法承受时,考虑对转移进行优化。常见的如维护区间最大/最小值,通过数据结构或者DP进行优化。

最新文章

  1. PHP通用分页(Pager)类
  2. Android热修复之微信Tinker使用初探
  3. mac os 体验
  4. C#面向对象编程进阶(一) ——实现栈
  5. Linux及安全——Linux基础实践
  6. mybatis分页插件PageHelper的使用(转)
  7. 6、android 普通日志输出到SD卡
  8. 千万别把js的正则表达式方法和字符串方法搞混淆了
  9. android基础学习之布局
  10. asp.net获取文件夹下的所有文件
  11. 1354 - IP Checking(水题)
  12. 【cocos2d-js官方文档】二十五、Cocos2d-JS v3.0中的单例对象
  13. 解决adb command not found以及sdk环境配置
  14. 201521123012 《Java程序设计》第一周学习总结
  15. Java面试准备之数据库
  16. 转载:escape,encodeURI,encodeURIComponent有什么区别?
  17. JAVA程序员_常用英语
  18. 『TensorFlow』分布式训练_其二_单机多GPU并行&amp;GPU模式设定
  19. JAVA引用的种类
  20. Oralce分析函数

热门文章

  1. RF上传图片各种失败坑,使用pywin32来操作windows窗体
  2. jmeter的脚本增强之参数化
  3. Linux命令应用大词典-第41章 MySQL数据库
  4. C 判断成绩是否及格
  5. Open MPI集群运行
  6. Python入门(5)
  7. Python变量常量及注释
  8. Python—集合(在我的世界,你就是唯一)
  9. 测试报告M2
  10. phpcms开启在线编辑模版 方法