[CodeVs3196]黄金宝藏(DP/极大极小搜索)
2016-04-02 23:44
537 查看
题目大意:给出n(≤500)个数,两个人轮流取数,每次可以从数列左边或者右边取一个数,直到所有的数被取完,两个人都以最优策略取数,求最后两人所得分数。
显然这种类型的博弈题,第一眼就是极大极小搜索+记忆化,但是我并不是很会极大极小搜索TAT。然后第二眼发现可以用DP写,而且显然比极大极小搜索好写啊。这一类的题有一个最普遍的做法,预处理出前缀和,然后f[i][j]表示从第i个数到第j个数先手可得到的最大得分,则有$$f[i][j]=sum[j]-sum[i-1]-min(f[i+1][j],f[i][j-1]);$$【第i个数到第j个数的和减去min(第i+1个数到第j个数先手可得到的最大得分,第i个数到第j-1个数先手可得到的最大得分)】
要注意一点,由于$$f[i][j]$$需要用到$$f[i+1][j]和f[i][j-1]$$,所以我们需要枚举的是i到j这个区间的长度,先把区间长度小的计算出来,才能计算区间长度大的,一开始就被这个坑了,果然我还是太弱了= =。。。
代码如下:
var n,i,j,res,sum:longint; a:array[0..1000] of longint; f:array[0..600,0..600] of longint; function max(a.b:longint):longint; begin if a>b then exit(a); exit(b); end; function dfs(l,r:longint):longint; begin if f[l,r]<>maxlongint then exit(f[l,r]); if l+r=n then begin f[l,r]:=0; exit(0); end; f[l,r]:=max(a[l+1]-dfs(l+1,r),a[n-r]-dfs(l,r+1)); exit(f[l,r]); end; begin readln(n); sum:=0; for i:=1 to n do begin read(a[i]); inc(sum,a[i]); end; for i:=0 to n do for j:=0 to n-i do f[i,j]:=maxlongint; res:=dfs(0,0); writeln((sum+f[0,0]) div 2,' ',(sum-f[0,0]) div 2); end.View Code
相关文章推荐
- 学习笔记:XML与JSON的介绍与对比
- jq checked 设置问题
- 【GDOI模拟】数树数
- 20160402_[转]联合体(union)的使用方法及其本质
- Windows隐藏工具栏并使程序窗口全屏显示
- 2013 第39级台阶
- android应用基础开发
- 有哪些 Android 的开源界面库?
- 设计模式(二十二)--桥接模式
- Java之从任务中产生返回值方式1
- 缓冲区的一些测试代码
- Ubuntu下怎么安装Kompozer
- [6644] 02 Apr 23:11:58.976 # Creating Server TCP listening socket *:6379: bind: No such file or directory
- SDAU课程练习2 1025
- C# 客户端服务器学习(一)
- ssh连接提示“REMOTE HOST IDENTIFICATION HAS CHANGED! ”解决办法
- html不可不知的15条编码原则
- Java 理论与实践: 正确使用 Volatile 变量
- Java异常
- 构建之法阅读笔记03